|
4.3. 总结
open函数的主要操作就是为文件初始化inode,初始化文件结构,刷新进程文件链表。
5.creat 函数
asmlinkage long sys_creat(const char __user * pathname, int mode){
return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
}
从上面的简短的实现代码可以看出,creat的系统调用直接以O_CREAT|O_WRONLY|O_TRUNC标识调用open函数实现的。
6.read 函数
6.1.原型与参数
ssize_t read(unsigned int fd, char * buf, size_t count)
read函数是从打开的文件中读取数据。如read成功,则返回读到的字节数。如已到达文件的尾端,则返回0。如果失败,则返回-1。有多种情况可使实际读到的字节数少于要求读字节数:
• 读普通文件时,在读到要求字节数之前已到达了文件尾端。例如,若在到达文件尾端之前还有30个字节,而要求读100个字节,则read返回30,下一次再调用read时,它把返回0 (文件尾端)。
• 当从终端设备读时,通常一次最多读一行(第11章把介绍怎么样改变这一点)。
• 当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。
• 某些面向记录的设备,例如磁带,一次最多返回一个记录。
读操作从文件的当前位移量处开始,在成功返回之前,该位移量增加实际读得的字节数。
6.2.实现分析
6.2.1.主要函数调用关系图
sys_read (参见6.2.2 )
| ------------- vfs_read (参见6.2.3)
|
6.2.2.主调用函数sys_read
asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count)
{
struct file *file;
ssize_t ret = -EBADF;
int fput_needed;
// 从进程文件链表中根据fd获取file文件表,如果没有这个文件表,则返回EBADF错误
file = fget_light(fd, &fput_needed); // fput_needed标识是否需要更新file结构的count
if (file) {
loff_t pos = file_pos_read(file); // 获取file结构的pos位移参数
ret = vfs_read(file, buf, count, &pos); // 读取文件内容,参见6.2.2
file_pos_write(file, pos); // 更新file结构的pos位移参数
fput_light(file, fput_needed); // 更新文件count标识
}
return ret;
}
|
6.2.3.sys_read子函数vfs_read
vfs_read把调用文件驱动模块的read函数从磁盘中读入数据并返回。
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
ssize_t ret;
if (!(file->;f_mode & FMODE_READ))
return -EBADF;// 如果文件不允许读模式,则返回EBADF错误
if (!file->;f_op || (!file->;f_op->;read && !file->;f_op->;aio_read))
return -EINVAL;// 如果文件结构没有read函数指针,则返回EINVAL错误
if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
return -EFAULT;// 检查传入的参数是否超出了用户空间地址,如果是则返回EFAULT错误
// 通过inode结构lock当前要操作的区域,成功返回0
ret = rw_verify_area(READ, file, pos, count);
if (!ret) {
// 检查进程对文件是否有READ操作权限,成功,则返回0
ret = security_file_permission (file, MAY_READ);
if (!ret) {
if (file->;f_op->;read) // 调用文件驱动模块read函数读入数据
ret = file->;f_op->;read(file, buf, count, pos);
else // 否则调用直接磁盘读操作
ret = do_sync_read(file, buf, count, pos);
if (ret >; 0) {
// 通知目录,当前文件已经被访问
dnotify_parent(file->;f_dentry, DN_ACCESS);
current->;rchar += ret; // 刷新进程读数据计数器
}
current->;syscr++;
}
}
return ret;
}
|
共6页: 上一页 [1] [2] [3] [4] 5 [6] 下一页
|