glibc-2.15 : fopen 源码

来源:互联网 发布:淘宝网皮书包 编辑:程序博客网 时间:2024/05/18 03:30


0. 使用cscope查找fopen定义 (推荐)

$ cd glibc-2.15$ cscope -R
注: cscope的使用请移步这里
一些快捷键 :

    ctrl + ]   : 查找定义

    ctrl + t   : 返回上一个位置


1. 使用grep找到fopen的定义(效率低)

这里使用grep命令查找。

直觉告诉我,可以通过查找函数原型找到fopen的定义,于是,我输入了如下的命令。

(其实可以先简单的用grep查找,碰碰运气,如果输出结果不多,可以直接定位;如果结果太多了,就考虑使用正则表达式匹配了。或者会用ctags、cscope的同学请忽略这篇文章)

$ grep -E "int\W*fseek\W*\(FILE" * -rconform/data/stdio.h-data:function int fseek (FILE*, long int, int)libio/stdio.h:extern int fseek (FILE *__stream, long int __off, int __whence);manual/stdio.texi:@deftypefun int fseek (FILE *@var{stream}, long int @var{offset}, int @var{whence})

虽然使用grep得到了一些结果,但是都不是fopen的定义。

这是因为,glibc中的函数,一般通过宏进行定义。我们修改grep命令,再次查找。

$ grep -E "#\W*define\W*fopen\W*" * -rhurd/fopenport.c:#define fopencookie _IO_fopencookieinclude/stdio.h:#   define fopen(fname, mode) _IO_new_fopen (fname, mode)libio/stdio.h:#  define fopen fopen64

(⊙o⊙),看到第二行了吗,确实是个宏定义。(第三行的结果,我没有弄懂,请大家赐教)

需要继续查找 _IO_new_fopen 的定义

$ grep -E "_IO_new_fopen" * -rChangeLog.11:* libio/iofopen.c (_IO_new_fopen): Likewise.ChangeLog.13:(__fopen_internal): New function.  Split out from _IO_new_fopen.ChangeLog.13:(_IO_new_fopen): Call __fopen_internal.ChangeLog.15:_IO_old_fopen, _IO_new_fopen, _IO_fopen64, __fopen_internal,include/stdio.h:extern _IO_FILE *_IO_new_fopen (const char*, const char*);include/stdio.h:#   define fopen(fname, mode) _IO_new_fopen (fname, mode)libio/iofopen.c:# define _IO_new_fopen fopenlibio/iofopen.c:_IO_new_fopen (filename, mode)libio/iofopen.c:strong_alias (_IO_new_fopen, __new_fopen)libio/iofopen.c:versioned_symbol (libc, _IO_new_fopen, _IO_fopen, GLIBC_2_1);libio/iolibio.h:extern _IO_FILE *_IO_new_fopen (const char*, const char*);sysdeps/wordsize-64/iofopen.c:weak_alias (_IO_new_fopen, _IO_fopen64)sysdeps/wordsize-64/iofopen.c:weak_alias (_IO_new_fopen, fopen64)

_IO_new_fopen的定义就在 libio/iofopen.c 中

_IO_FILE *_IO_new_fopen (filename, mode)     const char *filename;     const char *mode;{      return __fopen_internal (filename, mode, 1);} 

继续查找__fopen_internal , 也在 libio/iofopen.c 中

_IO_FILE *__fopen_internal (filename, mode, is32)     const char *filename;     const char *mode;     int is32;{     struct locked_FILE  {     struct _IO_FILE_plus fp;#ifdef _IO_MTSAFE_IO    _IO_lock_t lock;#endif    struct _IO_wide_data wd;  } *new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));  if (new_f == NULL)    return NULL;#ifdef _IO_MTSAFE_IO  new_f->fp.file._lock = &new_f->lock;#endif#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T  _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd, &_IO_wfile_jumps);#else  _IO_no_init (&new_f->fp.file, 1, 0, NULL, NULL);#endif  _IO_JUMPS (&new_f->fp) = &_IO_file_jumps;  INTUSE(_IO_file_init) (&new_f->fp);#if  !_IO_UNIFIED_JUMPTABLES  new_f->fp.vtable = NULL;#endif  if (INTUSE(_IO_file_fopen) ((_IO_FILE *) new_f, filename, mode, is32)      != NULL)    return __fopen_maybe_mmap (&new_f->fp.file);  INTUSE(_IO_un_link) (&new_f->fp);  free (new_f);  return NULL;}    



2.源码分析

TODO



* 一些注释

grep 加上-E是使用 ”扩展的正则表达式“, 需要学习的请移步这里

其实,写成下面的形式也是可以的,但是如果某的返回值和和函数名字之间不只有一个空格时,会找不到函数原型的。

grep "int fseek (FILE" * -r


* Linux 的fopen 与 windows的fopen 之间的区别

linux下查看fopen的manpage,得知,fopen的第二个参数mode有一些需要注意的地方,先看原文:

The  mode  string  can  also include the letter 'b' either as a last character or as a character between the characters in any of the two-character stringsdescribed above.  This is strictly for compatibility with C89 and has no effect; the 'b' is ignored on  all  POSIX  conforming  systems,  including  Linux.(Other systems may treat text files and binary files differently, and adding the 'b' may be a good idea if you do I/O to a binary file and expect that yourprogram may be ported to non-UNIX environments.)

粗略的翻译一下:

linux中在mode中加上 'b' 仅仅是为了兼容C89。

但是windows平台上 ‘b’ 是为了以二进制形式进行IO。

为了提高可移植性,需要加上'b'。

那么为什么windows下要区分”文本模式“和”二进制模式“呢?

原因是windows使用CRLF(0x0D 0x0A)表示换行符(两个字节)。而*nix使用\n表示换行符。

在以”文本模式“读取文件时,会将读取到的CRLF(0x0D 0x0A)转化为单字节的0x0A,当遇到结束符CTRLZ(0x1A),就认为文件结束。

在以”文本模式“写文件时,会将所有的0x0A换成0x0D0x0A。

所以,在windows上打开linux上创建的文件会出现一些问题,原因就是换行符是不同的。


例如,有一个网络程序,需要在windows和linux之间传输文件,windows端的程序应该以二进制形式打开文件,然后进行传输。

这样才能将文件原封不动的传送到Linux。

然后Linux将文件传回时,windows以二进制方式接收,就可以得到原始文件了。



0 0
原创粉丝点击