每个运行中的程序称为“进程”。
每个进程一般有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);