linux中的open代码分析

sys_open()代码分析

open

应用程序在操作任何一个文件之前,必须先调用open()来打开该文件,即通知内核新建一个代表该文件的结构,并且返回该文件的描述符(一个整数),该描述符在进程内唯一。open()的格式如下:

int open(const char * pathname,int oflag, mode_t mode )

pathname:代表需要打开的文件的文件名;

oflag:表示打开的标识;

O_ACCMODE<0003>: 读写文件操作时,用于取出flag的低2位。
O_RDONLY<00>: 只读打开
O_WRONLY<01>: 只写打开
O_RDWR<02>: 读写打开
O_CREAT<0100>: 文件不存在则创建,需要mode_t
O_EXCL<0200>: 如果同时指定了O_CREAT,而文件已经存在,则出错 
O_NOCTTY<0400>: 如果pathname代表终端设备,则不将此设备分配作为此进程的控制终端
O_TRUNC<01000>: 如果此文件存在,而且为只读或只写成功打开,则将其长度截短为0  
O_APPEND<02000>: 每次写时都加到文件的尾端
O_NONBLOCK<04000>: 如果p a t h n a m e指的是一个F I F O、一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I / O操作设置非阻塞方式。
O_NDELAY<O_NONBLOCK>
O_SYNC<010000>: 使每次write都等到物理I/O操作完成。
FASYNC<020000>: 兼容BSD的fcntl同步操作
O_DIRECT<040000>: 直接磁盘操作标识,每次读写都不使用内核提供的缓存,直接读写磁盘设备
O_LARGEFILE<0100000>: 大文件标识
O_DIRECTORY<0200000>: 必须是目录
O_NOFOLLOW<0400000>: 不获取连接文件
O_NOATIME<01000000>: 暂无

mode:当新创建一个文件时,需要指定mode参数,以下说明的格式如宏定义名称<实际常数值>: 描述如下:

 S_IRWXU<00700>:文件拥有者有读写执行权限
 S_IRUSR (S_IREAD)<00400>:文件拥有者仅有读权限
 S_IWUSR (S_IWRITE)<00200>:文件拥有者仅有写权限
 S_IXUSR (S_IEXEC)<00100>:文件拥有者仅有执行权限
 S_IRWXG<00070>:组用户有读写执行权限
 S_IRGRP<00040>:组用户仅有读权限
 S_IWGRP<00020>:组用户仅有写权限
 S_IXGRP<00010>:组用户仅有执行权限
 S_IRWXO<00007>:其他用户有读写执行权限
 S_IROTH<00004>:其他用户仅有读权限
 S_IWOTH<00002>:其他用户仅有写权限
 S_IXOTH<00001>:其他用户仅有执行权限

当open()系统调用进入内核时候,最终调用的函数为SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode),该函数位于fs/open.c中,下面转入分析该代码。

SYSCALL_DEFINE3

SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)
{
   
	long ret;

	if (force_o_largefile())
		flags |= O_LARGEFILE;
	//检查内核是不是支持大文件,如果是大文件的话就对flags标记对应的标记位置位	
	ret = do_sys_open(AT_FDCWD, filename, flags, mode);
    //完成主要的open工作,AT_FDCWD表示从当前目录开始查找
	/* avoid REGPARM breakage on x86: */
	asmlinkage_protect(3, ret, filename, flags, mode);
	return ret;
}

该函数主要调用do_sys_open()来完成打开工作,do_sys_open()的代码分析如下。

do_sys_open

内核实现真正的打开

long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
{
   
	struct open_flags op;
	int lookup = build_open_flags(flags, mode, &op);
	char *tmp = getname(filename);
     //将文件名参数从用户态拷贝至内核,调用函数get_name();
	int fd = PTR_ERR(tmp);
    //PTR_ERR函数用于将指针型的错误码转换为长整型的。 
//IS_ERR函数用于判断指针函数的返回值是否为错误码,如果是,则表示该指针函数执行失败。
	if (!IS_ERR(tmp)) {
   
		fd = get_unused_fd_flags(flags);
        //用于获取尚未占用的文件描述符;
		if (fd >= 0) {
   
			struct file 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值