open()在Linux内核的基本实现

1.基本说明

在用户态使用open()时,必须向该函数传入文件路径和打开权限。这两个参数传入内核后,内核首先检查这个文件路径存在的合法性,同时还需检查使用者是否有合法权限打开该文件。如果一切顺利,那么内核将对访问该文件的进程创建一个file结构。

在用户态,通常open()在操作成功时返回的是一个非负整数,即所谓的文件描述符(fd,file deor);并且,用户态后续对文件的读写操作等都是通过fd来完成的。由此可见fd与file结构在内核中有一定的关联。

具体的,内核使用进程描述符task_struct来描述一个进程,而该进程所有已打开文件对应的file结构将形成一个数组files(其为files_struct结构),内核向用户返回的fd便是该数组中具体file结构的索引。默认情况下,每个进程创建后都已打开了标准输入文件、标准输出文件、标准错误文件,因此他们的文件描述符依次为0、1和2。

2.函数分析2.1.do_sys_open

明白了上述原理,那么open系统调用在内核中的基本实现过程就很清晰。根据系统调用入口函数的命名规则,open系统调用的入口函数应该为sys_open。不过,目前内核统一使用SYSCALL_DEFINEn宏来描述系统调用入口函数,因此可以在open.c文件中找到该入口函数,具体如下所示:

1SYSCALL_DEFINE3(open, constchar__user *, filename, int, flags, int, mode);

该函数内部直接调用了do_sys_open函数,具体声明如下:

1longdo_sys_open(intdfd, constchar__user *filename, intflags, intmode);

这个函数的参数基本上与open系统调用的参数一致。

该函数可以简单概括open系统调用的功能:

1.通过build_open_flags()将用户态的flags和mode转换成对应的内核态标志;

2.由于filename是用户态的内存缓冲区(使用了__user修饰),因此通过getname()将文件名从用户态拷贝至内核态;

3.get_unused_fd_flags()为即将打开的文件分配文件描述符;也就是在当前进程的files数组中寻找一个未使用的位置;

4.通过do_filp_open()为文件创建file结构体;

5.如果创建file成功,则通过fd_install()将fd和file进行关联;如果创建file失败,通过put_unused_fd()将已分配的fd返回至系统,并且根据file生成错误的fd;

6.通过putname()释放在内核分配的路径缓冲区;

7.返回fd;

当open系统调用执行完毕后,fd返回用户态,内核态新建了与其关联的file;对于每个进程而言,通过files_struct来记录其所打开的文件,具体通过fd_array数据保存fd和file的对应关系,fd本质为该数组的索引。

3.总结

至此,open的基本实现过程已经分析完毕。不过do_sys_open函数没有直接体现文件路径的查找过程,这部分将是整个open系统调用内核实现的重要部分。如果对此感兴趣,可以继续阅读本系列后续文章。

原文链接:https://www.sohu.com/a/197368455_467784

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值