首先分析一下sys_read系统调用(内核版本为2.6.19.4)。
源代码如下(摘自fs/read_write.c)
这里用到了fget_light(),file_pos_read(),vfs_read(),file_pos_write(),fput_light()。
- file_pos_read()和file_pos_write()(均位于fs/read_write.c)用来读取当前文件指针(即当前文件操作的位置)
- fget_light()和fput_light()(位于fs/file_table.c和include/linux/file.h)必须是成对出现的!fget_light在当前进程的struct files_struct中根据所谓的用户空间文件描述符fd来获取文件描述符。另外,根据当前fs_struct是否被多各进程共享来判断是否需要对文件描述符进行加锁,并将加锁结果存到一个int中返回, fput_light则根据该结果来判断是否需要对文件描述符解锁
- vfs_read()(位于fs/read_write.c)调用具体文件系统的read函数来完成读操作,代码如下:
通过源码可以看出,内核中无法直接使用sys_read()来进行文件操作,因为sys_read()总会在当前进程的struct files_struct中查找文件。
(除非内核想对当前进程打开的某个文件进行操作,不知道这种情况是否存在)
内核可以使用vfs_read()来进行文件操作,一个例子如下
主要区别就是在操作前调用set_fs()(位于arch/x86/boot/boot.h)将当前fs段寄存器设为KERNEL_DS,在完成后再调用该函数将fs段寄存器设为原来的值,这样做的原因尚不明,希望高手指点。
问题:
1.内核中atomic_read()加锁是怎么进行的
2.还可调用kernel_read()(位于fs/exec.c,在include/linux/fs.h中声明)来直接读文件,该函数中完成了fs段期存期的保存,但找不到对应的kernel_write()函数