一、文件共享
每个进程都有一个自己的文件描述符表。在一个进程中,一个文件被打开之后,会分配一个文件描述符,一个文件表表项,一个v节点表。其中文件表保存文件状态,包括:读、写、追加、同步、非阻塞等。其中文件表项是不能共享的,文件被打开一次,就会分配一个文件表项;v节点表示可以共享的,两个不同的文件表项可以指向同一个v节点表。
(1)、一个进程打开两个文件模型:
(2)、一个进程两次打开同一个文件
我们可以通过例子证明上面的模型,示例:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0)
int main()
{
int fd1,fd2;
char buf[1024];
fd1 = open("aa.txt",O_RDWR);
if (fd1 == -1)
ERR_EXIT("open error");
read(fd1,buf,5);
printf("read1:%s\n",buf);
fd2 = open("aa.txt",O_RDWR);
if(fd2 == -1)
ERR_EXIT("open error");
read(fd2,buf,5);
printf("read2:%s\n",buf);
write(fd1,"AAAaa",5);
read(fd2,buf,5);
printf("read fd2:%s\n",buf)
close(fd1);
close(fd2);
return 0;
}
执行结果:
s@ubuntu:~/sys$ cat aa.txt
abcdeAAAaa
s@ubuntu:~/sys$ gcc open2.c
s@ubuntu:~/sys$ ./a.out
read1:abcde
read2:abcde
read fd2:AAAaa
s@ubuntu:~/sys$
说明一个进程打开两次的相同文件会有两个文件表项,但是共享v节点。
(3)、两个进程打开同一个文件
两个进程打开一个文件描述符可以相同,因为每个进程都有自己的文件描述符表。示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0)
#define MAJOR(a) (int)((unsigned short)a>>8)
#define MINOR(a) (int)((unsigned short)a & 0xFF)
int filetype(struct stat *buf);
int main(int argc,char* argv[])
{
int infd;
int outfd;
int ret;
if ((ret = fork()) > 0)
{
infd = open("aa.txt",O_RDONLY);
printf("in:%d\n",infd);
}
else
{
outfd = open("aa.txt",O_WRONLY);
printf("out:%d\n",outfd);
}
wait(&ret);
return 0;
}
结果:
in:3
out:3
文件描述符相同,说明每个进程都有自己的文件描述符表。
(4)、复制文件描述符
复制之前:
复制之后:
可以通过复制文件描述符实现输出重定向到文件,示例:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0)
int main()
{
int fd;
fd = open("aa.txt",O_WRONLY);
if (fd == -1)
ERR_EXIT("open error");
close(1);
dup(fd);//等价于dup2(fd,0);
printf("Hello\n");
return 0;
}
结果"Hello"没有输出到屏幕,而是输出到文件,因为此时标准输出文件描述符1已经指向打开文件aa.txt。