进步

发表于:2007-07-04来源:作者:点击数: 标签:
原来奇怪socket在connect失败时为什么不释放(见commer一书7.7的例子),现在终于明白了。 另外,即使不close file,进程结束产生的结果和close file几乎没有区别(读 linux 源代码的印象) fclose似乎必须使用,因为还有用户态缓冲。 查了一下 http://www.e

原来奇怪socket在connect失败时为什么不释放(见commer一书7.7的例子),现在终于明白了。

另外,即使不close file,进程结束产生的结果和close file几乎没有区别(读linux源代码的印象)

fclose似乎必须使用,因为还有用户态缓冲。

查了一下

http://www.eecs.wsu.edu/~cs360/libio.html 国外的课程质量高啊

(1). fopen() uses a string for Mode, where "r" stands for READ, "w" for
         WRITE. It returns a pointer to a FILE structure. The FILE structure
         contains a buffer, whose size usually matches that of BLKSIZE. In
         addition, it also has pointers, counters and status variables for
         manipulating the buffer.

         fopen() first allocates and initialize a FILE structure in (heap area
         of) the UserImage. It then issues an open() syscall for the file. If
         the open() syscall suclearcase/" target="_blank" >cceeds, it records the returned fd in the FILE
         structure, and returns a pointer to the FILE structure. Otherwise, it
         frees the FILE structure and returns a NULL pointer.

         It is important to note that the FILE structure, which is allocated/
         freed dynamically, is in the process' UserImage. This means that calls
         to Library I/O functions are ordinary function calls, not syscalls. 
3. Algorithms of fread(), fwrite() and fclose()

3-1. The algorithm of fread() is as follows:

     (1). On the first call to fread(), the FILE structure's buffer is empty.
          fread() uses the saved file descriptor fd to issue a
                  n = read(fd, fbuffer, BLKSIZE);
          syscall to fill the local fbuffer. Then, it initializes fbuffer's
          pointers, counters and status variables to indicate that there is a
          block full of data in the local buffer.
          It then tries to satisfy the fread() call from the local buffer by
          copying data to the program's buffer area. If the local buffer does
          not have enough data, it issues additional read() syscalls to fill
          the local buffer, until the needed number of bytes is satisfied (or
          end of file is reached). After copying data to the program's buffer
          area, it updates the local buffer's pointers, counters, etc. getting
          ready for next fread() request.  It then returns the acutal number of
          objects read to the calling place.

     (2). On each subsequent call to fread(), it tries to satisfy the call from
          the FILE structure's local buffer. It issues a read() syscall to
          refill the local buffer whenever the buffer becomes empty.

          Thus, fopen() accepts calls from user program on one side and issues
          read() syscalls to the Kenrel on the other. Except for the read()
          syscalls, all processing of fread() are performed in the User Mode.
          It enters the Kernel mode only when needed and it does so in a way
          that matches the Kernel's behavior for best efficiency. It provides
          automatic buffering mechanism so that user programs do not have to
          worry about such detailed operations.

3-2 fwrite():

     The algorithm of fwrite() is similar to that of fread() except for the
     data movement direction.  Initially the FILE structure's local buffer is
     empty. On each call to fwrite(), it writes data to the local buffer, and
     adjust the buffer's pointers, counters and status variable to keep track
     of the number of bytes in the buffer. If the buffer becomes full, it
     issues a write() syscall to write the entire buffer to Kernel

3-3. USE syscalls OR Library Functions?
         
     Based on the above discussion, we can now answer the question of whether
     to use syscalls or Libray functions to do file I/O?

     fread() relies on read() to copy data from Kernel to the local buffer,
     from which it copies data to the program's buf area. In contrast, read()
     copies data from Kernel directly to the program's buf area.  Thus, for
     read/write data in units of BLKSIZEs, read() is inherently more efficient
     than fread() because it only needs one copying operation instead of two.
     Therefore, in the above C programs, the one that uses syscalls is actually
     more efficient than the other that uses Library I/O functions.  However,
     if the read/write is not in units of BLKSIZE, fread() and fwrite() may be
     far more efficient. For example, if we insists on R/W one byte at a time,
     fread() and fwrite() would be far better because they enter Kernel Mode
     only to fill or flush the local buffer, not on every byte. Here, we have
     implicitly assumed that entering Kernel mode is more expensive than
     staying in User mode. This is indeed true.

3-4. Algorithm of fclose():

     fclose() first flushes the local buffer if the file was opened for WRITE.
     Then it issues a close() syscall to close the file descriptor.  Finally
     it frees the FILE structure and resets the FILE pointer to NULL.

3-5. Other Modes for fopen(): 重要

     The Mode parameter in fopen() may be specified as

       "r", "w", "a" : for READ, WRITE, APPEND, or with a +, which means to
                       create the file if it does not exist.
       "r+" : for R/W, without truncating the file.
       "w+" : for R/W, but truncate the file first.
       "a+" : for R/W by appending.

     However, when a file is fopened for both R/W, there may be restrictions on
     the use of mixed fread() and fwrite() calls. The specification requires
     that at least one fseek() or ftell() be used between every pair of fread()
     and fwrite().

     Example: This program yields different results when run under HP Unix and
              Linux.

              #include
              FILE fp; char buf[1024];
              main()
              {
                  fp = fopen("t.c", "r+");   /* for both R/W */
                  fread(buf, 1, 20, fp);     /* read 20 bytes */
                  fwrite(buf,1, 20, fp);     /* write to the same file */
              }


     Linux gives the right result, which modifies the bytes from 20 to 39. But
     HP Unix appends 40 bytes to the end of the original file.

     The difference stems from the non-uniform treatment of R/W pointers in the
     two systems.  Recall that fread()/fwrite() issue read()/write() syscalls
     to fill/flush the local buffer.  While read()/write() use the R/W pointer
     in the file's OFTE, fread()/fwrite() use the local buffer's R/W pointer in
     the FILE structure.  Without a fseek() to synchronize these two pointers,
     the results depend on how are they used in the implementations. In order
     avoid any inconsistencies, follow the man pages. For the example program,
     the results become i.netical (and correct) if you insert a line

                  fseek(fp, (long)20, 0);

     between the fread() and fwrite().

原文转自:http://www.ltesting.net