Linux基础篇十 ——文件操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Monamokia/article/details/51746083

提起文件操作我们就不得不说起两个重要的部分,文件描述符和文件指针,相信很多人都会分不清这两个看起来十分相似的东西,但是,实际上他们两的差别是十分大的。我们先来看看他们到底是什么。

文件描述符:在linux系统中打开文件就会获得文件描述符,它是个很小的正整数。每个进程在PCB中保存着一份文件描述符表文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针。

文件指针:C语言中使用文件指针做为I/O的句柄。文件指针指向进程用户区中的一个被称为FILE结构的数据结构。FILE结构包括一个缓冲区和一个文件描述符。而文件描述符是文件描述符表的一个索引,因此从某种意义上说文件指针就是句柄的句柄(在Windows系统上,文件描述符被称作文件句柄)。

每个进程在PCB中都保存着一份文件描述符表,文件描述符就是这个表的索引,已打开的文件在内核中用file结构体表示,文件描述符表中的指针指向file结构体。在file结构体中维护File Status Flag(file结构体的成员f_flags)和当前读写位置(file结构体的成员f_pos)。每个file结构体都指向一个file_operations结构体,这个结构体的成员都是函数指针,指向实现各种文件操作的内核函数。

eg:在用户程序中read一个文件描述符,read通过系统调用进入内核,然后找到这个文件描述符所指向的file结构体,找到file结构体所指向的file_operations结构体,调用它的read成员所指向的内核函数以完成用户请求。

每个file结构体都有一个指向dentry结构体的指针我们传给openstat等函数的参数的是一个路径,例如/home/akaedu/a,需要根据路径找到文件的inode为了减少读盘次数,内核缓存了目录的树状结构,称为dentry cache,其中每个节点是一个dentry结构体,只要沿着路径各部分的dentry搜索即可

每个dentry结构体都有一个指针指向inode结构体inode结构体保存着从磁盘inode读上来的信息。

inode结构体有一个指向super_block结构体的指针。super_block结构体保存着从磁盘分区的超级块读上来的信息

#include <stdio.h>
#include <errno.h>
#include <string.h>
#define _PATH_ "./log"
int main()
{
FILE *fp = fopen(_PATH_, "w");
if( NULL == fp ){
printf("%s open file %s error, error code is : %d\n",__FUNCTION__, _PATH_, error);
return 1;
}
char *str = "this is a test\n";
int i=0;
while( i<100 ){
fwrite(str, 1, strlen(str),fp);
i++;
}
fclose(fp);
return 0;
}
上面的例子里我们使用的是fwrite,接下来再让我们看一个write符来操作文件的例子

#include <unistd.h>
#include <stdio.h>
int glob = 6; 
char buf[] = "a write to stdout\n";
int
main(void)
{
int var;
pid_t pid;
var = 88;
if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
perror("write error");
printf("before fork\n"); /* we don't flush stdout */
if ((pid = fork()) < 0) {
perror("fork error");
}else if (pid == 0) { /* child */
glob++; /* modify variables */
var++;
}else {
sleep(2); /* parent*/
}
printf("pid = %d, glob = %d, var = %d\n", getpid(), glob,var);
exit(0);
}
**write是不带缓冲的(系统调用不带缓冲)

**标准I/O是缓冲的,标准输出到终端是行缓冲,否则就变成了全缓冲。

有时将结构定位到标准输出和文件里出现的结果是不同的,但是我们不必感到困惑,只不过是父进程的缓冲区的内容还没被刷新出来之前就被子进程复制了,所以子进程也会在

程序结束的时候在文件里刷新出重复的内容。

**父子进程的使用相同的描述符共享操作同一个文件。

fork之后处理的⽂件描述符有两种常见的情况:
⽗进程等待⼦进程完成。在这种情况下,⽗进程⽆需对其描述符做任何处理。当⼦进程终⽌后,⼦进程对⽂件偏移量的修改已执⾏的更新。
⽗⼦进程各⾃执⾏不同的程序段这种情况下,在fork之后,⽗⼦进程各⾃关闭他们不需要使⽤的⽂件描述符,这样就不会⼲扰对⽅使⽤⽂件描述符。




阅读更多

没有更多推荐了,返回首页