2

예를 들어 K&R 2 (8.6 예 - 디렉토리 나열)을보고있었습니다. Linux 명령 ls 또는 Windows 'dir의 다운 된 버전입니다. 이 예는 opendir, readdir과 같은 함수 구현을 보여줍니다. 나는 한 번에 하나씩 코드를 입력하려고했지만 여전히 작동하지 않는다. 그것이하는 것은 점 (현재 디렉토리에 대한)을 인쇄하고 종료한다는 것입니다.디렉토리에서`read` 시스템 호출 사용

readdir 구현에서 코드에서 발견 한 흥미로운 점은 시스템 호출을 openread과 같은 디렉터리에서 호출한다는 것입니다. 같은 뭔가 -이 코드를 실행하면 폴더 이름 "dirname"가 일부 파일이 경우에도

int fd, n; 
char buf[1000], *bufp; 

bufp = buf; 
fd = open("dirname", O_RDONLY, 0); 
n = read(fd, bufp, 1000); 
write(fd, bufp, n); 

나는 더 출력을 얻을 수 없습니다.

또한,이 책은 구현이 버전 7 및 시스템 V UNIX 시스템위한 것이라고 말했다. 이것이 리눅스에서 작동하지 않는 이유입니까?

다음은 코드 http://ideone.com/tw8ouX입니다.

그래서 리눅스는 read 디렉토리에서 시스템 호출을 허용하지 않습니까? 아니면 뭔가 다른 원인입니까?

답변

1

사실 Linux에서는 디렉토리에 read을 사용할 수 없습니다. man page을보고 errno EISDIR을 검색하십시오. 당신은) (

fildes 인수가 디렉토리를 참조하고 구현이 디렉토리를 읽을 사용하여 읽을 수 허용하지 않습니다 ...

에게 기능이있는 경우 실패 할 것이다 읽기()와 pread()를 찾을 수 또는 pread(). 대신 readdir() 함수를 사용해야합니다.

. 그럼에도 불구하고 다른 유닉스가 허용한다.

+0

그래서'readdir'은 리눅스에서 시스템 호출입니까? – ShuklaSannidhya

+0

솔직히'readdir()'자체가 시스템 호출이거나 다른 것을 호출하는지 모르겠습니다. 테스트 프로그램을 작성하고,'strace'로 실행하고, 발견하고 말해주십시오. 나도 궁금해. –

5

버전 7 UNIX에서는 하나의 유닉스 파일 시스템 만 있었고 그 디렉토리는 단순한 온 - 디스크 형식이었습니다 : 배열은 struct direct입니다. 그것을 읽고 결과를 해석하는 것은 사소했습니다. syscall이 중복되었을 수 있습니다.

현대에서는 Linux 및 다른 유닉스 계열 시스템 (ext4, ZFS, NTFS!)에서 마운트 할 수있는 파일 시스템이 많이 있으며, 그 중 일부는 복잡한 디렉토리 형식을 가지고 있습니다. 임의의 디렉토리의 원시 바이트를 사용하면 아무 것도 할 수 없습니다. 따라서 커널은 추상 객체로 디렉토리에 대한 일반적인 인터페이스를 제공 할 책임이 있습니다. readdir은 해당 인터페이스의 중심 부분입니다.

일부 현대의 유닉스에서는 디렉토리에 read()이 여전히 허용됩니다. 리눅스 역사는 90 년대에 시작되었는데, 디렉토리상의 read()이 절대로 유용하지 않으므로 리눅스는 결코 그것을 허용하지 않았다.

리눅스는 readdir 시스템 콜을 제공하지만 더 이상 사용되지 않아 더 이상 사용되지 않습니다. getdents. readdir은 한 번에 하나의 디렉토리 항목 만 반환하므로 디렉토리의 파일 목록을 얻기 위해 루프에서 readdir syscall을 사용하면 모든 루프 반복마다 커널을 입력하게됩니다. getdents는 여러 항목을 버퍼로 반환합니다.

readdir은 표준 인터페이스이므로, glibc는 readdir 시스템 콜 대신 getdents 시스템 콜을 호출하는 readdir 기능을 제공합니다. 보통 프로그램에서는 소스 코드에서 readdir을 볼 수 있지만 strace에서는 getdents를 볼 수 있습니다. C 라이브러리는 getchar()을 호출 할 때 일반 파일의 stdio에서와 마찬가지로 버퍼링을 통해 성능을 향상시키는 데 도움이됩니다. 한 번에 한 바이트 씩 read() 번 대신 read()을 입력해야합니다.

오래 전 컴파일 된 실행 파일을 실행하거나 C 라이브러리를 우회하는 방법을 벗어나지 않으면 원래 버퍼되지 않은 readdir syscall을 최신 Linux 시스템에서 사용하지 마십시오.

+0

나는 왜 이것이 실패했는지 찾기 위해 너무 오래 동안 노력했다. 여전히, C의 근속 기간에 대한 증거는 K & R 책의 180 페이지를 현재의 구현과 큰 불일치없이 만나 보았습니다. – mickadoo

+0

'readdir'은 시스템 호출이 아닙니까? – Alex

+0

@Alex 그것은 원래의 리눅스에 있었고, 그것을 제거하면 아무런 이익이없는 호환되지 않는 사용자 공간 ABI가 생기기 때문에 여전히 i386 (32 비트)에서 지원됩니다. amd64와 같은 getdents 뒤에 도착한 아키텍처에는 이전 시스템 호출이 없습니다. –