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以二进制方式接收,就可以得到原始文件了。
- glibc-2.15 : fopen 源码
- glibc-2.15 : fseek 源码
- glibc源码
- [glibc源码分析] bzero
- strlen glibc 源码分析
- glibc--memcpy源码分析
- glibc--strcpy源码分析
- glibc -- strlen源码分析
- glibc---memcpy源码
- glibc fread函数源码剖析
- glibc函数exit源码分析
- glibc
- glibc
- glibc
- Glibc
- glibc
- glibc
- glibc
- 批处理bat schtasks 启动远程应用
- Android抽奖(大转盘,随机)
- Android蓝牙设备的检测
- android scroller overscroller用法
- 更改归档日志路径
- glibc-2.15 : fopen 源码
- 目标检测“DPMs are CNNs”
- PASSION之Linux命令详解
- 小巧而又强大的翻译神器--QTranslate
- Java嵌套类
- 基于HashHeap的LFU实现
- js typeof
- swift 初级 断言
- Ubuntu 安装mysql和简单操作