glibc-2.15 : fopen 源码
2015-10-27 16:49
309 查看
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" * -r conform/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*" * -r hurd/fopenport.c:#define fopencookie _IO_fopencookie include/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" * -r ChangeLog.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 fopen libio/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 strings described 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 your program 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以二进制方式接收,就可以得到原始文件了。
相关文章推荐
- ASP.NET动态网站制作(19)-- C#(2)
- ARM-Linux应用程序自动升级以及自动回滚的实现
- 疯狂配置第一弹:Linux下安装Java环境
- 【推荐】腾讯android镜像(做Android开发的得好好利用下这个网站,国内的大公司还是可以滴……)
- zabbix监控端口状态
- L8.1 lvs+heartbeat-ldirectord实现高可用负载均衡
- select top 变量问题
- distinct top執行順序
- [nginx] 网上最全面nginx教程(近100篇文章整理)
- this 用法之作用域:$("option:selected",this)
- linux系统安装(三)-跨系统文件拷贝工具Winscp
- linux下解压命令大全
- linux的环境变量文件enviroment 、profile、bashrc和.bashrc以及.bash_profile
- linux 下查看网卡工作速率
- Linux和windows下检查jsp后门文件的方法
- WebService报错:org.apache.cxf.interceptor.Fault: No such operation
- Linux C 重定向简单范例
- Discuz! X3.0/X3.1/X3.2通用 Apache伪静态规则
- JDK介绍 && linux下JDK 环境变量设置
- 使用 Apache Pig 处理数据