1:文件理解
文件=内容+属性,因此空文件在磁盘上也占用空间。
文件用路径名+文件名作为标识文件的唯一性。
对文件的操作,就是对文件的内容+属性的操作。
在linux中,如果没有指定文件路径,默认在当前路径下执行操作。
总结:在c语言中调用文件操作函数的时候,即使代码没有进行链接(二进制->可执行exe文件),也不会进行对文件的操作,只有程序运行起来,才有操作。因此对文件进行操作,就是进程对文件的操作。
文件操作也就是进程和被打开文件的关系。
1.1:c语言文件操作函数
FILE* fp = fopen(wjw.c,"r");//只读方式打开文件
if(fp == NULL)
{
perror("fail open");
return 1;
}
char buffer[] = "abcd";
fwrite(p,1,strlen(buffer),fp);
与fwrite差不多。
1.2:操作系统的文件操作函数
我们使用man 2 open命令查看系统级别的open函数,
第一个参数是文件名,第二个参数是一个标记位,第三个参数是文件权限。(linux默认掩码是0002)
1.2.1:标记位
以比特位传递选项,只能有一个比特位为1,也就是1,2,4,8.....选项可以是O_WRONLY,O_RDONLY,O_RDWR,O_CREAT(没有文件的时候创建该文件),O_TRUNC(有该文件的时候,覆盖文件内容),O_APPEND(追加)。
运用|可以将多个参数一起传入。
结果如上。
1.2.2:文件权限
第三个参数如果不传入,则会导致乱码。
因为系统默认掩码umask不为0,创建出来的文件权限是664,
因此如果想让代码设置的0666就是文件权限,可以使用umask(0),文件最大权限是666,目录最大权限是777,想要知道文件的权限可以使用“拿走的思想(减去)”,但是具体的计算规则是^~umask。
1.2.3:文件操作函数
read和write的第一个参数都是fd,fd是文件描述符,属于内核级别的东西。buf就是想要读或者写入的文件,第三个是操作系统级别的文件大小。
在c语言层次,我们读文件都是要读写到\0结束,但是\0是语言提供的,与操作系统没有关系,因此操作系统在识别的时候可能会出错,因此我们在传带\0的字符串的时候,需要用sizeof减1。
1.3:文件描述符fd
可以看到文件描述符是从3开始打印的,这是什么原因呢?
实际上我们系统还有3个文件,stdin,stdout,stderr,分别对应键盘,显示器,显示器。
其实在内核系统中有这样一组结构。
task_struct就是进程pcb,pcb中存储一个struct files_struct *files 的指针,找到struct files_struct数组,在这个数组中存在一个struct file*的指针数组fd_array,数组的下标就是文件描述符,数组的元素就是每一个被打开的文件的结构体。因此stdin和stdout和stderr是默认打开的文件,占用着下标0和1和2,所以此后打开的文件下标从3开始。
文件描述符的分配规则:在文件描述符表按从小到大顺序寻找最小且没有被占用的fd。
1.3:重定向
当我们关闭0对应的stdin,
输出fd是0,这就是把本来在3号位置的文件重新定向到了0号对应的地方。
当我们关闭1(stdout)的时候呢
什么也没有打印,那么内容去哪儿了?此时我们引入重定向的概念。
实际上就是fd1指向的不再是stdout,而是新的这个log.txt文件,这种方式我们可以通过重定向函数dup2完成。而重定向的本质就是每个文件描述符都是一个内核中文件描述信息数组的下标,对应有一个文件的描述信息用于操作文件,而重定向就是在不改变所操作的文件描述符的情况下,通过改变描述符对应的文件描述信息(数组中的元素)进而实现改变所操作的文件
重定向有3种
1.3.1:重定向函数dup2
dup2的第一个参数是旧的fd,第二个是新的fd,其实使用起来就是把旧的fd对应的文件描述信息(当前下标对应的元素,也就是指向的某个文件的指针file*)替换新的fd对应的文件描述信息。