xinshuming 发表于 2009-10-31 19:02

fopen 在linux下是如何实现的

一直都只是在使用C library写程序, 却从来不是很清楚库函数是如何实现的. 比如简单的fopen, 在linux下如何实现的?
下载了glibc的源代码, 看到了下面的代码, 不清楚这是不是fopen的实现代码? 如果是的话, 最后实现open操作的 _IO_file_fopen 是在哪里实现的?
那位研究过的XDJM给点提示, Thanks!

#   define          fopen(fname, mode)          _IO_new_fopen (fname, mode)

---------------------------------------------------------

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

----------------------------------------------------------------------

_IO_FILE *
__fopen_internal (filename, mode, is32)
   const char *filename;
   const char *mode;
   int is32;
{
....................................
if (INTUSE(_IO_file_fopen) ((_IO_FILE *) new_f, filename, mode, is32)
      != NULL)
    return __fopen_maybe_mmap (&new_f->fp.file);

..................................
}

kouu 发表于 2009-10-31 20:17

libc与内核打交道的部分都是通过内核提供的系统调用来实现的, fopen使用的是open系统调用.
写个C程序, 然后用strace使用启动一下, 就可以看到程序执行过程中使用到的系统调用...

xinshuming 发表于 2009-10-31 21:28

原帖由 kouu 于 2009-10-31 20:17 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
libc与内核打交道的部分都是通过内核提供的系统调用来实现的, fopen使用的是open系统调用.
写个C程序, 然后用strace使用启动一下, 就可以看到程序执行过程中使用到的系统调用...

谢谢你的回复!

我的理解也是应该通过系统调用open来处理的, 不过在glibc里面怎么找不到调用的代码呢?

比如像下面这样直接调用的代码:

FILE *fopen(const char *filename, const char *mode)
{
      ..........................
      open (filename, ..........);
         .........................
}

buaadallas 发表于 2009-10-31 22:07

回复 #3 xinshuming 的帖子

我上次发了一个open()系统调用的帖子,也是想弄明白在glibc中如何实现这个系统调用,但是,最后还是失败了,只能通过libc.so.6这个库文件看到open的汇编实现代码。编译系统这个东西的确很复杂,里面用了大量的宏,比如weak_alias,PSUEDO, DO_CALL,所以有时候之间查open或者fopen关键字很难找到对应的实现代码。。
anyway,fopen最后是要调用open()的,如果哪天你找到了这个调用过程,麻烦反馈一下:)祝好运!

sparkzh 发表于 2009-10-31 23:09

大部分的库函数都是通过系统调用实现的

distliu 发表于 2009-11-01 10:28

把文件名传给VFS,VFS查找DEntry,找到对应的inode,然后调用文件系统和底层的函数,将文件打开

duanjigang 发表于 2009-11-02 17:21

看看VFS的原理应该大概就知道了,但是具体细节还要看代码

hum998 发表于 2010-04-07 21:06

大概有几种封装方式:
1)直接在代码调用sys,比如setgid()等
文件: glibc-2.9\sysdeps\unix\sysv\linux\i386\setgid.c
代码片段:
...
   INLINE_SETXID_SYSCALL (setgid, 1, gid)
...
   
2)封装到.S汇编代码中,比如socket()等
文件: glibc-2.9\sysdeps\unix\sysv\linux\i386\sokect.S
代码片段:
...
.globl __socket
...

3)使用shell脚本生产syscall代码,比如open()等
   生成syscall代码的脚本:glibc-2.9\sysdeps\unix\make-syscalls.sh
   syscall列表:glibc-2.9\sysdeps\unix\sysv\linux\i386\syscalls.list

byjxy 发表于 2010-04-12 08:51

学习

linux初学三月 发表于 2010-04-15 12:31

大概有几种封装方式:
1)直接在代码调用sys,比如setgid()等
文件: glibc-2.9\sysdeps\unix\sysv\linux\ ...
hum998 发表于 2010-04-07 21:06 http://linux.chinaunix.net/bbs/images/common/back.gif


    这个写得真好
页: [1] 2
查看完整版本: fopen 在linux下是如何实现的