linux底层文件访问

每个运行中的程序称为“进程”。
每个进程一般有3个已经打开的文件描述符:

  • 0:标准输入
  • 1:标准输出
  • 2:标准错误

1.write系统调用

man 2 write,可以查看具体文档信息。

函数原型:

/* 
函数功能:系统调用write把缓冲区buf的前count个字节写入与文件描述符fd关联的文件里。 
参数:fd--文件描述符
	 buf--缓冲区
     count--字节数  
返回值:返回实际写入的字节数。
       如果是0:表示没有写入任何数据
       如果是-1:表示write调用出错了,错误代码保存在全局变量errno里 
*/
#include <unistd.h> 

ssize_t write(int fd, const void *buf, size_t count);

示例:

#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

#define STD_INPUT  0
#define STD_OUTPUT 1
#define STD_ERR	   2

int main()
{
	int ret=0;
	char buf[] = "hello world\n";
	ret = write(STD_OUTPUT, buf, sizeof(buf));
	if(ret != sizeof(buf))
		write(STD_ERR, "Write error happened!\n", 22);
	else if(ret > 0)
		printf("write %d bytes\n", ret);
	exit(0);
}

编译:
gcc write.c -o write

运行:
root@ubuntu:/home/CPP# ./write
hello world
write 13 bytes

2.read系统调用

man 2 read,可以查看具体信息。
函数原型:

/*
函数功能:从与文件描述符fd相关联的文件里读入count个字节,放入到buf数据区里。
参数:fd--文件描述符
     buf--数据区
     count--字节数
返回值:返回实际读入的字节数。
	   0--没有读入任何数据,已经到达了文件末尾
	   -1--read调用出现了错误
*/
#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

示例:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#define STD_INPUT  0
#define STD_OUTPUT  1
#define STD_ERR    2

int main()
{
	char buffer[128];
	int nbytes;

	nbytes = read(STD_INPUT, buffer, 128);
	if(-1 == nbytes)
		strerror(errno);

	if(write(STD_OUTPUT, buffer, nbytes) != nbytes)
		printf("Write error happened\n");

	exit(0);
}

程序从标准输入读入数据,再写道标准输出。

编译:
root@ubuntu:/home/CPP# gcc read.c -o read

运行:
root@ubuntu:/home/CPP# ./read < draft.txt // 以draft.txt的内容作为程序的输入
I am learning to read!

3.open系统调用

== man 2 open,可以查看具体信息。==

函数原型:

/*
函数功能:open建立了一条到文件或设备的访问路径。
参数:pathname--访问路径,准备打开的文件或设备的名字
     flags--指定打开文件所采取的动作。
     		flags参数通过必要的文件访问模式和可选的文件访问模式组合而成。
     		open必须指定的下列文件模式之一:
     			O_RDONLY		以只读方式打开
     			O_WRONLY		以只写方式打开
     			O_RDWR			以读写方式打开
     		可选模式:
     			O_APPEND		把写入数据追加到文件的末尾
     			O_TRUNC			把文件长度设置为0,丢弃已有的内容
     			O_CREAT			按参数mode中给出的访问模式创建文件
     			O_EXCL			与O_CREAT一起使用,使用该模式可以防止2个程序同时创建同一个文件。如果文件已存在,则open失败。
     			还有很多需要查看手册页。
 返回值:成功--返回一个新的文件描述符,非负的整数。新文件描述符总是使用未用的描述符的最小值。
 		失败--返回-1,并设置全局变量errno来说明错误原因。
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

示例:

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>

int main()
{
	int fd;

	fd = open("./draft.txt", O_WRONLY);// 以写方式打开当前目录下的draft.txt
	if(fd == -1)
	{
		strerror(errno);
		exit(-1);
	}
	
	printf("The fd is %d\n", fd);
	exit(0);
}

编译:
root@ubuntu:/home/CPP# gcc open.c -o open

运行:
root@ubuntu:/home/CPP# ./open
The fd is 3

一般每个程序所能打开的文件数是有限的,通常由limits.h头文件中的常量OPEN_MAX定义。它的值随系统的不同而不同。
在Linux系统里,这个限制可以在系统运行时调整,在Linux里它并不是一个常量,通常一开始被设置为256.
代码:

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
	printf("open max is %d\n", FOPEN_MAX);//ubuntu19.10里写OPEN_MAX报错了,改成FOPEN_MAX

	exit(0);
}

运行:
root@ubuntu:/home/CPP# ./open_max
open max is 16
这里最大能打开的是16个文件。

4.文件访问权限的初始值

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags, mode_t mode);

如果使用带有O_CREAT标志的open调用来创建文件时,就得使用带有mode参数的open调用。
参数mode由以下几个标志位按位或后得到:

  • S_IRUSR 读权限,文件属主
  • S_IWUSR 写权限,文件属主
  • S_IXUSR 执行权限,文件属主
  • S_IRGRP 读权限,文件所属组
  • S_IWGRP 写权限,文件所属组
  • S_IXGRP 执行权限,文件所属组
  • S_IROTH 读权限,其它用户
  • S_IWOTH 写权限,其他用户
  • S_IXOTH 执行权限,其它用户

代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

int main()
{
	//在当前目录下创建一个文件test.txt,文件权限为rw-r-----。
	int fd = open("./test.txt", O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP);
	if(-1 == fd){
		strerror(errno);
		exit(-1);
	}

	printf("The fd is %d\n", fd);
	exit(0);
}

查看文件权限:
root@ubuntu:/home/CPP# ls -al test.txt
-rw-r----- 1 root root 0 Apr 27 00:24 test.txt

影响文件权限的因素:

  • 指定的访问权限在创建文件时才可以使用
  • 用户掩码(umask),mode值会和当时的用户掩码的反值做AND操作。open中调用的标志实际上只是发出设置文件访问权限的请求,所请求的访问权限是否会被设置取决于当时的umask的值。

关于umask

man umask,查看具体信息。

umask是一个系统变量,作用:当文件被创建时,为文件的访问权限设定一个掩码。执行umask命令可以改变它的值。它由3个八进制数字组成。

不同用户的umask:
root@ubuntu:/home/chenjianzhen/CPP# umask
0022 // 后面3个与一般权限有关,第一个是特殊权限
chenjianzhen@ubuntu:~/CPP$ umask
0002

| 数字 |取值 |含义|
|–|--|
| 1| 0 |允许属主任何权限|
| | 4 |禁止属主的读权限|
| | 2 |禁止属主的写权限|
| | 1 |禁止属主的执行权限|
| 2| 0 |允许组任何权限|
| | 4 |禁止组的读权限|
| | 2 |禁止组的写权限|
| | 1 |禁止组的执行权限|
| 3| 0 |允许其它用户任何权限|
| | 4 |禁止其它用户的读权限|
| | 2 |禁止其它用户的写权限|
| | 1 |禁止其它用户的执行权限|

代码示例:

//请求文件权限为rw-rw-rw-,即0666.
int fd = open("./test.txt", O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);

最终的文件权限:申请的文件权限 & 取反后的umask
0666 & ~022 = 0644
即-rw-r–r--。

查看文件权限:
root@ubuntu:/home/CPP# ls -al test.txt
-rw-r–r-- 1 root root 0 Apr 27 01:14 test.txt

5.close系统调用

函数原型:

#include <unistd.h>
/*
函数功能:终止文件描述符fd与对应文件之间的关联。
参数:fd--要关闭的文件描述符
返回值:成功--返回0
	   失败--返回-1
*/
int close(int fd);
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值