fopen () 대신 Open ()을 사용해야 할 일반적인 이유가 있습니까?

StackOverflow https://stackoverflow.com/questions/544662

  •  23-08-2019
  •  | 
  •  

문제

나는 꽤 오랜 시간이 지나서 C에서 작은 프로젝트를하고 있습니다. 여기에는 일부 파일 처리가 포함됩니다. 다양한 문서에서 반환하는 기능이 있음을 알았습니다. FILE * 처리 (작은 정수) 디스크립터를 반환하는 다른 사람. 두 기능 세트 모두 필요한 동일한 기본 서비스를 제공하므로 실제로 사용하는 것은 중요하지 않습니다.

그러나 나는 수집 지혜에 대해 궁금합니다. 사용하는 것이 더 낫습니까? fopen() 그리고 친구, 또는 open() 그리고 친구들?

편집하다 누군가가 버퍼링 된 대 Undufered 및 액세스 장치를 언급 했으므로이 작은 프로젝트의 한 부분이 Fuse에서 사용자 공간 파일 시스템 드라이버를 작성하는 것이라고 추가해야합니다. 따라서 파일 레벨 액세스는 "파일"(예 : 이미지)에서 장치 (예 : CDROM 또는 SCSI 드라이브)에 쉽게있을 수 있습니다.

도움이 되었습니까?

해결책

"fopen"이 휴대용이라는 반대 의견은 "오픈"은 가짜가 아닙니다.

Fopen은 LIBC의 일부이며 Open은 POSIX 시스템 호출입니다.

각각은 그들이 오는 곳만큼 휴대용입니다.

fopen'ed 파일에 대한 I/O (당신은 그것이 그것을 할 수 있고, 실제적인 목적으로) libc에 의해 버퍼링 된 경우, 파일 디스크립터 Open () 'ed는 libc에 의해 버퍼링되지 않습니다 (일반적으로 잘 될 수 있습니다. 파일 시스템에 버퍼링되었지만 ()가 파일 시스템의 파일이 아닙니다.

예를 들어 /dev /sg0과 같은 장치 노드, 또는 /dev /tty0과 같은 Fopen'ing의 요점은 무엇입니까? 파일에서 ioctl을 할 것입니다 *? 행운을 빌어 요.

어쩌면 당신은 o_direct와 같은 일부 플래그로 열고 싶을 수도 있습니다. fopen ()와 의미가 없습니다.

다른 팁

Unix와 같은 시스템을 고수하고 있고 원하는 경우 Open ()을 사용하는 것이 좋습니다.

  • 파일 생성시 유닉스 권한 비트를보다 세밀하게 제어 할 수 있습니다.
  • C 버퍼링 스트림 I/O 함수와 달리 읽기/쓰기/MMAP와 같은 하위 레벨 기능을 사용하십시오.
  • 파일 디스크립터 (FD) 기반 IO 스케줄링 (폴링, 선택 등) 사용 파일에서 FD를 얻을 수 있지만 fileno ()를 사용하여 파일에서 FD를 얻을 수 있지만 파일 기반 스트림 함수를 FD 기반 함수와 혼합하지 않도록주의해야합니다. .
  • 특수 장치 열기 (일반 파일 아님)

표준 C 함수이므로 위에서 언급 한 기능은 그렇지 않으므로 Fopen/Fread/Fwrite를 최대한 활용하는 것이 좋습니다.

Fopen은 열린 것보다 높은 레벨에서 작동합니다 .... Fopen은 C ++에서 읽은 스트림 추상화와 유사한 파일 스트림에 대한 포인터를 반환합니다.

Open은 열린 파일에 대한 파일 디스크립터를 반환합니다 ... 스트림 추상화를 제공하지 않으며 비트와 바이트를 직접 처리 할 책임이 있습니다 ... 이것은 FOPEN에 비해 낮은 레벨에 있습니다.

stdio 스트림은 버퍼링되며 Open () 파일 설명자는 그렇지 않습니다. 필요한 것에 따라 다릅니다. 다른 하나에서 하나를 만들 수도 있습니다.

int fileno (file * stream) 파일 *, 파일 * fdopen (int fildes, const char * mode)에 대한 파일 디스크립터를 반환하면 파일 디스크립터에서 파일 *을 생성합니다.

혼합 버퍼 및 부러되지 않은 IO를 인터 믹싱 할 때 조심하십시오. fflush ()로 플러시하지 않을 때 버퍼의 내용을 잃을 수 있기 때문입니다.

예. 낮은 수준의 손잡이가 필요한 경우.

UNIX 운영 체제에서는 일반적으로 파일 핸들 및 소켓을 교환 할 수 있습니다.

또한 낮은 수준의 핸들은 파일 포인터보다 ABI 호환성을 향상시킵니다.

일반적으로 표준 라이브러리 (Fopen)를 사용하는 것을 선호해야합니다. 그러나 직접 열기를 사용해야하는 경우가 있습니다.

떠오르는 한 가지 예는 256 개의 파일이 열린 후 Fopen이 실패하게 만드는 이전 버전의 Solaris에서 버그를 해결하는 것입니다. 이는 int 대신 구조물 파일 구현에서 FD 필드에 서명되지 않은 숯을 잘못 사용했기 때문입니다. 그러나 이것은 매우 구체적인 경우였습니다.

읽다() & 쓰다() 부패하지 않은 I/O를 사용하십시오. (FD: 정수 파일 설명 자)

프레드 () & fwrite () 버퍼링 된 I/O를 사용하십시오. (파일* 구조 포인터)

파이프에 쓰여진 이진 데이터 쓰다() 그렇지 않을 수도 있습니다 이진 데이터를 읽을 수 있습니다 프레드 (), 바이트 정렬, 가변 크기 등으로 인해 쓰레기 촬영.

대부분의 저수준 장치 드라이버 코드는 부패하지 않은 I/O 통화를 사용합니다.

대부분의 애플리케이션 수준 I/O는 버퍼링을 사용합니다.

사용 파일* 관련 기능은 기계별로 괜찮습니다. 그러나 이진 데이터의 읽기 및 쓰기에서 다른 아키텍처에서는 휴대 성이 손실됩니다. fwrite ()는 버퍼링 된 I/O이며 64 비트 아키텍처를 위해 쓰여지고 32 비트에서 실행되는 경우 신뢰할 수없는 결과를 초래할 수 있습니다. 또는 (Windows/Linux). 대부분의 OSS는이를 방지하기 위해 자체 코드 내에 호환 매크로를 가지고 있습니다.

저수준 바이너리 I/O 휴대 성 용 읽다() 그리고 쓰다() 다른 아키텍처에서 컴파일 될 때 동일한 이진 읽기 및 쓰기를 보장합니다. 기본적인 것은 바이너리 스위트 전체에서 어떤 방법을 선택하고 일관성을 유지하는 것입니다.

<stdio.h>  // mostly FILE*  some fd input/output parameters for compatibility
             // gives you a lot of helper functions -->
List of Functions
       Function      Description
       ───────────────────────────────────────────────────────────────────
       clearerr      check and reset stream status
       fclose        close a stream
       fdopen        stream open functions //( fd argument, returns FILE*)                      feof          check and reset stream status
       ferror        check and reset stream status
       fflush        flush a stream
       fgetc         get next character or word from input stream
       fgetpos       reposition a stream
       fgets         get a line from a stream
       fileno        get file descriptor   // (FILE* argument, returns fd) 
       fopen         stream open functions
       fprintf       formatted output conversion
       fpurge        flush a stream
       fputc         output a character or word to a stream
       fputs         output a line to a stream
       fread         binary stream input/output
       freopen       stream open functions
       fscanf        input format conversion
       fseek         reposition a stream
       fsetpos       reposition a stream
       ftell         reposition a stream
       fwrite        binary stream input/output
       getc          get next character or word from input stream
       getchar       get next character or word from input stream
       gets          get a line from a stream
       getw          get next character or word from input stream
       mktemp        make temporary filename (unique)
       perror        system error messages
       printf        formatted output conversion
       putc          output a character or word to a stream
       putchar       output a character or word to a stream
       puts          output a line to a stream
       putw          output a character or word to a stream
       remove        remove directory entry
       rewind        reposition a stream
       scanf         input format conversion
       setbuf        stream buffering operations
       setbuffer     stream buffering operations
       setlinebuf    stream buffering operations
       setvbuf       stream buffering operations
       sprintf       formatted output conversion
       sscanf        input format conversion
       strerror      system error messages
       sys_errlist   system error messages
       sys_nerr      system error messages
       tempnam       temporary file routines
       tmpfile       temporary file routines
       tmpnam        temporary file routines
       ungetc        un-get character from input stream
       vfprintf      formatted output conversion
       vfscanf       input format conversion
       vprintf       formatted output conversion
       vscanf        input format conversion
       vsprintf      formatted output conversion
       vsscanf       input format conversion

따라서 기본적인 사용을 위해 나는 관용구를 너무 많이 혼합하지 않고 개인적으로 위의 것을 사용합니다.

대조적으로

<unistd.h>   write()
             lseek()
             close()
             pipe()
<sys/types.h>
<sys/stat.h>
<fcntl.h>  open()
           creat()
           fcntl() 
all use file descriptors.

이들은 바이트 읽기 및 쓰기 바이트에 대한 세밀한 제어를 제공합니다 (특수 장치 및 FIFO (파이프)에 권장).

다시 한 번, 필요한 것을 사용하되, 관용구와 인터페이스에서 일관성을 유지하십시오. 대부분의 코드 기반이 하나의 모드를 사용하는 경우, 그렇지 않은 실제 이유가 없다면이를 사용하십시오. 두 I/O 라이브러리 기능 세트는 매우 신뢰할 수 있으며 하루에 수백만 번 사용됩니다.

노트-- CI/O를 다른 언어와 인터페이스하는 경우 (Perl, Python, Java, C#, Lua ...) 체크 아웃 C 코드를 작성하고 문제를 저장하기 전에 해당 언어의 개발자가 추천하는 것.

Fopen과 그 사촌은 완충됩니다. 열고 읽고 쓰기는 버퍼링되지 않습니다. 귀하의 신청서는 신경 쓰지 않을 수도 있습니다.

FPRINTF 및 SCANF에는 형식 텍스트 파일을 읽고 쓸 수있는 더 풍부한 API가 있습니다. 읽기 및 쓰기 바이트의 기본 배열을 사용하십시오. 변환 및 서식은 손으로 제작되어야합니다.

파일 설명자와 (파일 *)의 차이는 실제로 중요하지 않습니다.

랜디

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top