fopen 과 open의 차이에 관하여

qprk의 이미지

솔라리스에서 작업을 하다가 발견한 것입니다.

하나의 프로세스에서

fopen 으로 파일을 열때는 256개밖에 열리지 않고
open으로 파일을 열때는 시스템에 설정되어 있는만큼 파일을 열수 있었습니다.

이에 관하여 설명을 듣고 싶습니다..

문제 는 open을 사용하는것으로 해결을 하였지만
더 자세한 사항을 알고 싶내요.. ^^;

uleech의 이미지

저도 잘아는 편이 아니라 정확하게는 말씀못드리지만
(고수분들이 틀리면 지적해주시겠죠.)

open은 system call이고 fopen은 c언어에서 지원하는 함수일겁니다.
fopen은 독자적인 버퍼를 이용해서 파일을 열고 open은
system 버퍼를 이용해서 연다고.. 그 차이인것 같습니다.

eminency의 이미지

음... fopen은 open의 wrapper함수 아닌가요? wrapper라고 표현하는게 맞는지 모르겠는데...

open은 파일 디스크립터를 되돌려주는데 fopen은 내부에서 open을 호출하고 그 파일 디스크립터와 파일 스트림을 위한 버퍼 등등으로 구조체를 할당해 되돌려 주는 걸로 알고 있습니다.

즉 fopen은 open에 비해 추가적인 메모리를 더 필요로 하기 때문에 그런게 아닐까 싶네요...

노루가 사냥꾼의 손에서 벗어나는 것 같이, 새가 그물치는 자의 손에서 벗어나는 것 같이 스스로 구원하라 -잠언 6:5

moonzoo의 이미지

제 생각으로는 fopen, open의 차이가 아니라고 생각됩니다.

fopen으로 열어도 시스템의 최대치 만큼 열수 있습니다..

파일 디스크립터는 fopen 과 open의 차이가 실제로 없습니다.

무언가 다른 부분에서 잘못 되서 그런것 같습니다..

kihlle의 이미지

libio.h 헤더파일을 다들 아시겠지만

fopen에 쓰이는 FILE구조체는 _IO_FILE로서 멤버로 file descriptor를
갖고있습니다. 따라서 fileno() 와 같은 함수로 FILE 구조체와 fd 간에
변환도 가능하구요.

따라서 제가 알기로는 ulimit 에서 지정된 파일열기제한값만큼의 파일을
오픈할수 있는 것으로 알고 있습니다. 동일프로세스 내에서 256개밖에
열수없었다는 것은 무엇인가 다른 요인이 있을 것입니다. 만일 그렇다면
시스템호출이냐 아니냐의 차이가 원인일수도 있습니다.

플랫폼에 따라서는 내부적 구현이 둘다 유사하게 돌아가기도 합니다.
일례로 AIX상의 aiocb 구조체를 보면(대형시스템에서는 시스템콜로써
asynchronous i/o가 구현됩니다) 멤버에 FILE 구조체가 포함되는
것을 볼수 있습니다. (시스템콜이 FILE구조체를 참조합니다)

homeless

mastercho의 이미지

제가 보기엔 fopen은 C언어 표준 라이브러리고요

open은 유닉스 전용함수입니다

내부적으로는 fopen을 open으로 구현했을거라 보이네요

승자는 자기보다 우월한 사람을 보면 존경심을 갖고 그로부터 배울 점을 찾지만 패자는 자기보다 우월한 사람을 만나면 질투심을 갖고 어디 구멍난 곳이 없는지 찾는다.
- 하비스

cinsk의 이미지

ISO C Standard에서 fopen으로 동시에 열 수 있는 파일의 갯수는 FOPEN_MAX로 정의하고 있습니다. (<stdio.h>) 참고하시길..

mastercho님이 말씀하신 것처럼, fopen(3)은 ISO C Standard library function이고, open(2)는 POSIX.1 표준 함수입니다.

monpetit의 이미지

mastercho wrote:
제가 보기엔 fopen은 C언어 표준 라이브러리고요

open은 유닉스 전용함수입니다


글쎄요... 전 Turbo C 2.0부터 사용해 보았습니다만, DOS에서도 open/close 함수를 사용했습니다. 게다가 지금도 Visual C++ 런타임으로 _open/_close 함수가 있습니다. 앞에 underline이 들어가 있긴 하지만 유닉스의 open/close와 똑같은 기능을 할 겁니다.
최종호의 이미지

Solaris 쪽의 FILE 구조체 선언을 쫓아가 보시면

struct __FILE_TAG       /* needs to be binary-compatible with old versions */
{
#ifdef _STDIO_REVERSE
        unsigned char   *_ptr;  /* next character from/to here in buffer */
        ssize_t         _cnt;   /* number of available characters in buffer */
#else
        ssize_t         _cnt;   /* number of available characters in buffer */
        unsigned char   *_ptr;  /* next character from/to here in buffer */
#endif
        unsigned char   *_base; /* the buffer */
        unsigned char   _flag;  /* the state of the stream */
        unsigned char   _file;  /* UNIX System file descriptor */
        unsigned        __orientation:2; /* the orientation of the stream */
        unsigned        __ionolock:1;   /* turn off implicit locking */
        unsigned        __filler:5;
};

_file 이라는 필드가 unsigned char 로 되어 있는 것을 보실 수 있습니다.
(Solaris 7, Solaris 8기준. Solaris 2.6도 unsigned char 였던 것으로 기억합니다.)

따라서 이 녀석이 가리킬 수 있는 파일디스크립터가 256개 밖에 안되기 때문에 일어나는 일입니다.
아마 제 기억으로는 256번 이상 불려도 fopen()이 실패하지는 않았던 것 같은데 mod 256 이 되니까 원했던 파일이 아니라 다른 파일을 가리켰던 것 같습니다만, 확인해 봐야겠네요.

참고로 AIX(4.3.3)와 Tru64(5.1) 는 short _file; 로 디스크립터를 표현하고 있고, HP-UX (11.0)은 unsigned char __fileL; unsigned char __fileH; 로 나누어서 표현하네요.

monpetit의 이미지

조금 전에 찾은 관련 문서입니다. 참고하세요.
http://www.ece.eng.wayne.edu/~gchen/ece5650/faq.htm#_3)_What_is

Quote:
3) What is the difference between open(),read(), write(), close(), etc. and fopen(), fread(), fwrite(), fclose(), etc.?

Answer: The first group are the Unix system calls for I/O which are direct entry points into the kernel. They can be used not only for files but also for IPC channels (such as PIPE, FIFO) and Sockets. The second group are the standard I/O library functions, providing a higher level interface between a process and the kernel with features such as buffering, line-by-line input, formatted output, and the like. The second group will be finally implemented with the first group. With network programming, however, there are times when the Unix system calls must be used.

mach의 이미지

uleech wrote:
저도 잘아는 편이 아니라 정확하게는 말씀못드리지만
(고수분들이 틀리면 지적해주시겠죠.)

open은 system call이고 fopen은 c언어에서 지원하는 함수일겁니다.
fopen은 독자적인 버퍼를 이용해서 파일을 열고 open은
system 버퍼를 이용해서 연다고.. 그 차이인것 같습니다.


fopen()은 라이브러리이고 라이브러리 수준에서 버퍼링을 수행합니다. 그러나, 결국 운영체제를 거쳐야 IO를 수행할 수 있고, open()을 호출할 수 밖에는 없습니다. open()은 운영체제로의 파일액세스를 위한 창구입니다. 버퍼링 및 포맷팅등의 코딩이 귀찮아서 fopen을 비롯한 fxxxx()시리즈를 사용하는 것은 어쩔 수 없다지만, 저는 개인적으로 지금까지 이를 사용하는것에 반대해왔고, 현재도 그러합니다. 가급적 버퍼는 프로그래머의 원천코드로 직접관리하는게 옳다고 생각합니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.