1、关于文件描述符
对于文件IO来说,一切都是围绕文件描述符来进行的。在linux系统中,所有打开的文件都有一个对应的文件描述符。
文件描述符的本质是一个非负整数,当我们打开一个文件时,系统会给我们分配一个文件描述符。当我们对一个文件作读写操作时,我么使用open函数返回的这个文件描述符会标识该文件,并将其作为参数传递给read或write函数。
2、关于文件IO和标准IO
文件IO就是直接调用内核提供的系统调用函数。指的是应用程序可以直接通过内核提供的系统调用函数来进入内核,或者内核通过调用函数来进入调用函数;标准IO就是间接调用系统调用函数,是C函数库。
文件IO的头文件是unistd.h;标准IO的头文件是stdio.h;
文件IO是依赖于linux操作系统的;标准IO是不依赖于操作系统的,所以在任何操作系统下,使用标准IO,也就是c函数库操作文件的方法都是相同的。
对于linux系统来说,文件IO是个重点,文件IO包括open函数,creat、write、read等函数。
3、关于opeh函数的代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
main() {
int fd;
//为什么这里定义的fd(用来保存文件描述符)是int类型呢?因为在ubuntu中使用man 2 open命令
//打开可以看到open函数的返回值就是int型的
fd = open("a.c",O_CREAT|O_RDWR,0666);
//open"a.c文件",由于本来没有该文件,所以要用到O_CREAT
//由于用到了O_CREAT,所以需要第三个参数,也就是文件的权限
//此处设置的权限为0666,第一个0表示是八进制数,即:随意用户可读可写
//打开当前路径下的a.c
//看一下是否能够打开成功,如果没有这个文件,就会创建这个文件,因为加入了O_CREAT
if(fd<0){
printf("open is error\n");
}
printf("fd is %d\n",fd);
return 0;
}
代码在ubuntu界面的执行演示:
topeet@ubuntu:~$ su root
密码:
root@ubuntu:/home/topeet# cd
root@ubuntu:~# cd /home/samba/linux+c_test/
root@ubuntu:/home/samba/linux+c_test# ls
a.out open.c test1 test1.c test2 test22 test2.c test.c
root@ubuntu:/home/samba/linux+c_test# gcc open.c -o open
root@ubuntu:/home/samba/linux+c_test# ./open
fd is 3
由于在该程序中,文件描述符0,1,2分别对应着标准输入,标准输出,标准出错。这三个都已经用到了,所以会输出打印值3.
若是把编程代码中的O_CREAT删掉(即找不到a.c文件的时候也不创建该文件啦),并把ubuntu界面的a.c文件也删除掉,看看会是什么样的运行结果?
注释:此处只在编程代码中删除了O_CREAT,并没有删除mode_t mode参数,但是由于没有O_CREAT参数,故第三个参数的mode_t mode是无效的。
root@ubuntu:/home/samba/linux+c_test# ls
a.c a.out open open.c test1 test1.c test2 test22 test2.c test.c
root@ubuntu:/home/samba/linux+c_test# rm -r a.c
root@ubuntu:/home/samba/linux+c_test# ls
a.out open open.c test1 test1.c test2 test22 test2.c test.c
root@ubuntu:/home/samba/linux+c_test# gcc open.c -o open2
root@ubuntu:/home/samba/linux+c_test# ./open2
open is error
fd is -1
运行结果显示报错,打开失败,返回值为-1.
在ubuntu界面使用ll命令查看文件的权限
root@ubuntu:/home/samba/linux+c_test# ll
总用量 720
drwxr-xr-x 2 root root 4096 3月 12 20:03 ./
drwxr-xr-x 4 root root 4096 3月 12 14:48 ../
-rw-r--r-- 1 root root 0 3月 12 20:03 a.c
-rwxr-xr-x 1 root root 8496 3月 12 14:51 a.out*
-rwxr-xr-x 1 root root 8592 3月 12 19:49 open*
-rwxr-xr-x 1 root root 8592 3月 12 20:01 open2*
-rwxr--r-- 1 root root 687 3月 12 20:04 open.c*
-rwxr-xr-x 1 root root 8496 3月 12 15:25 test1*
-rwxr--r-- 1 root root 195 3月 12 15:25 test1.c*
-rwxr-xr-x 1 root root 8496 3月 12 15:32 test2*
-rwxr-xr-x 1 root root 648071 3月 12 15:47 test22*
-rwxr--r-- 1 root root 205 3月 12 15:32 test2.c*
-rwxr--r-- 1 root root 104 3月 12 14:51 test.c*
可以看到关于a.c文件的权限为0644,为什么与设置的0666不一样么?
-rw-r–r-- 1 root root 0 3月 12 20:03 a.c
实际上,open函数在创建a.c的时候,第三个参数mode_t会与源码的取反进行一个相与,如何查看源码嘞?直接在ubuntu界面上输入umask
root@ubuntu:/home/samba/linux+c_test# umask
0022
可以看到,源码值为0022,则将其与权限均表示为二进制数,再进行计算
110 110 110
&
!( 000 010 010)
————————————————
=110 110 110
&
111 101 101
————————————————
110 100 100
将该数字表示为八进制为0664(第一个0表示是八进制数)