DKU-Embedded-Lab / The-Linux-Programming-Interface

The Linux Programming Interface: A Linux and UNIX System Programming Handbook
0 stars 0 forks source link

Chapter4, 5 : File I/O #2

Open bestjae opened 6 years ago

bestjae commented 6 years ago

스터디 자료 : The Linux Programming Interface 시간 : 1/2 ( PM 1:00 ~ PM 3:00 ) 장소 : 미디어센터 508 호

1. 스터디및 발표자료 작성

2. 연습문제 구현

3. 현재 스터디 질문 제출

ghost commented 6 years ago

5장

tmdgus1237 commented 6 years ago
SeungBu commented 6 years ago
kangworld commented 6 years ago
tmdgus1237 commented 6 years ago

[5장]

  1. fcntl() 함수의 cmd 인자에서 F_GETFL 과 F_GETFD 옵션의 차이점을 알고 싶습니다.

F_GETFL : open 등에 의해서 열려진 파일 지정자에 대한 flag 값을 읽어온다.

F_GETFD : close on exec 값을 조정한다. (보통 프로세스에서 exec 함수를 시켜서 새로운 프로세스를 실행시키면 이 새로운 프로세스는 기존의 프로세스의 이지를 덮어쓰게 된다. 그러면서 특별한 설정이 없을 경우 열린 파일 지정자를 그대로 넘겨주게 된다. 이를 상속이라고 한다. 기존에 열렸던 파일지정자들을 깨끗하게 정리하고 싶을 때 close-on-exec 시킨다고 말한다.)이는 FD_CLOEXEC 하나만 반환하는 특성을 갖는다. 세 번째 인자는 FD_CLOEXEC 플래그를 가져올 곳이다. ex) val = fcntl(fd, F_GETFD,0)

[참고] https://m.blog.naver.com/PostView.nhn?blogId=neakoo35&logNo=30131475424&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F

  1. I/O의 Nonblocking이 구체적으로 어떠한 상황을 말하는 것인지 궁금합니다.

blocking I/O 작업이 진행되는 동안 유저 프로세스는 자신의 작업을 중단한 채 대기해야한다. I/O작업이 CPU자원을 거의 쓰지 않기 때문에 이런 형태의 I/O는 리소스 낭비가 심하다.

non-blocking 유저 프로세스는 recvfrom함수를 호출하여 커널에게 해당 소켓으로부터 데이터를 받아오고 싶다고 요청하고 있다. 커널은 이 요청에 대해서 상대방의 데이터를 전송 받아서 recvBuffer에 저장하고, 유저에게 그 내용을 복사해줘야 한다. 상대방으로 부터 데이터를 받는 중에 recvBuffer가 비어있다면 유저 프로세스가 커널에게 받아올 수 있는 정보는 없다. 따라서 recvfrom 함수는 아직 작업 진행중이란 의미로 "EWOULDBLOCK"을 리턴한다. 이 결과를 받은 유저 프로세스는 다른 작업을 진행할 수 있다. 만약 recvBuffer에 유저가 받을 수 있는 데이터가 있다면, 버퍼로 부터 데이터를 복사하여 받아온다. recvBuffer는 커널이 가지고 있는 메모리에 적재되어 있으므로 메모리간 복사가 일어나 I/O보다 훨씬 빠른 속도로 데이터를 받아올 수 있다. 이때 recvfrom함수는 빠른 속도로 읽을 수 있는 데이터를 복사해주고 복사한 데이터의 길이와 함께 반환한다. 위의 모든 반환이 I/O의 진행시간과는 관계없이 빠르게 동작하기 때문에, 유저 프로세스는 자신의 작업을 오랜시간 중지하지 않고도 I/O 처리를 수행할 수 있다.

소켓에서 기본으로 blocking이 설정되어 있어 non-blocking 설정을 해주어야 한다.

[참고] http://ozt88.tistory.com/20

  1. readv()를 수행할 때, 호출 프로세스의 관점에서 커널은 file descriptor가 가리키는 파일과 사용자 메모리 사이에서 단일 데이터 전송을 수행한다고 하는데 단일 데이터 전송에 대해 알고 싶습니다.

readv() 함수의 중요한 속성은 원자적으로 완료된다는 것을 설명하기 위해 나온다. 그렇기에 단일 데이터 전송은 원자성을 위한 방법이라고 생각한다.

  1. file descriptor 복제를 dup와 fcntl로 할 수 있는데 각각의 장단점은 어떤 것이 있는지 궁금합니다.

fcntl에서 F_DUPFD를 사용하여 fd를 복제할 때, arg 값으로 복제할 fd를 지정할 수 있어 dup2 함수와 비슷하다고 본다. 이 두 개 함수의 차이점을 본다면 dup2() 함수는 사용자가 지정한 fd 로만 복제가 된다. 반면, F_DUPFD 는 사용자가 지정한 fd 보다 크거나 arg 이상의 값 중 가장 낮은 값으로 복제가 된다. fcntl(fd, F_DUPFD, 0)과 같이 arg 인자를 똑같이 하여 여러 번 수행하여도 새로운 파일 디스크립트를 열 수 있다는 장점이 있다고 생각한다.

ghost commented 6 years ago

[4장]

Q. lseek()함수에서 offset을 수정할 때 물리적 장치에 접근하지 않는다고 하는데 offset이 어디에 존재하며 왜 물리적 접근없이 수정할 수 있나요? A. 실제로 offset은 disk에 있는 파일에 있는 정보가 아니라 커널에 있는 file descriptor가 참조하는 file table에 담긴 정보입니다. 그리고 lseek() 함수는 이 file table에 있는 offset을 주어진 인자로 재배치시켜주는 기능을 하죠. 따라서 lseek() 함수는 실제 물리적 장치인 disk에 접근하지 않고 커널에서만 동작하는 함수인 것입니다.

Q. ioctl()함수는 주로 어떤 상황에서 이 함수를 사용하는 가에 대해 알고 싶습니다. A. ioctl() 함수는 외부와 연결된 device를 제어하는 함수입니다. ioctl() 함수를 device 파일에 적용시키면 이 device 파일과 연결된 device driver에 포함된 ioctl field에 있는 함수와 서로 매개변수와 인자를 주고받으며 통신하게 되는 것이죠. ioctl() 함수는 실제 사용자 공간에서 외부의 device의 상태를 확인하거나 device를 제어하고 싶을 때 사용되는 함수입니다.

Q. O_CREAT 할때 mode 인자지정을 안할시 새로운 파일의 권한이 스택에 있는 임의의값으로 설정된다하는데 스택에 어떤 임의의값들이 존재하나요? A. stack에 어떤 임의의 값이 설정되는지 확인하기 위해 O_CREAT 옵션을 준 open() 함수가 포함된 파일을 만들어 ASM 파일로 컴파일해보았는데요, 확인한 바로는 O_CREAT 옵션을 준 상황에서 세번째 인자로 mode를 지정을 하든 안하든 stack에서는 이 mode 인자를 위한 frame을 만들어주는 것으로 확인했습니다. 따라서 교재에 나와있는 임의의 값이라는 것은 mode 지정을 하지않더라도 stack에서 default로 만들어준 mode frame에 들어있는 값을 말하는 것같구요. 문제는 ASM 파일의 명령어 상으로는 그 값을 초기화를 시켜주지 않는데, mode 지정을 안한 상태로 creat된 파일은 항상 mode가 0000인 상태로 권한이 주어진다는 것입니다. 이는 아마 시스템 설정 상으로 0000으로 초기화시켜주는 것이 아닐까 생각이 드는데 좀더 공부해보도록 하겠습니다.

Q. lseek()가 파이프나 등등 적용할수없는 사례가있었는데 어떤이유로 적용이 안되는건가요? A. 어려웠던 질문이라 이 질문은 좀 더 공부하면서 채워나가도록 하겠습니다. 교수님께서는 lseek() 함수 자체의 동작방식이 pipe, FIFO, socket 과 같은 특수파일의 동작방식과는 맞지 않다고 말씀해주셨는데요. lseek() 함수의 동작 원리와 위의 특수파일들의 동작 원리에 대해 공부해보겠습니다.