关于open函数的内部问题
在Linux下(注意不是windows) 调用open会在内核中建立一个file结构,当然在task_struct(及PCB中)结构中,由一个file指针指向它,所有open是把内核中的文件file结构映射到用户空间中,用户空间就用文件描述符操作文件,但是当2个或者更多进程打开同一个文件或者在同一进程中重复打开一个文件,虽然也返回不同的文件描述符,但是文件描述符都是指向同一个file结构,唯一有变化的就是在file结构体中有个count(好象是,具体名字记不清除了)的字段会增加,以表示有多少进程在使用本文件;简单的说,如果用open以同一中方式打开同一个文件,在内核中都使用同一个file结构
可以参看以下代码:
#include
#include
#include
#include
#include
#include
#include
int main( void )
{
int fd1, fd2;
char str[10];
fd1 = open( "test", O_CREAT | O_RDWR );//这里O_CREAT不是打开方式,只是告诉内核如果test不存在就建立,如果存在就忽略
assert( fd1 != -1 );
printf( "file Number is: %d\n", fd1 );
fd2 = open( "test", O_RDWR );
assert( fd2 != -1 );
printf( "file Number is: %d\n", fd2 );//这里验证返回了不一样的文件描述符
write( fd2, "Hello", 5 );
write( fd2, "pig", 3 );//这里我们用fd2写文件
read( fd1, str , 8 ); //这里我们用fd1读文件
str[9] = '\n';
printf( "read file is :%s\n", str ); //这里输出的是Hellopig,可以验证虽然是2个不同的文件描述符,但是是使用的同一个file结构
return 0;
}
以上代码是验证一个进程里2个不同open调用使用一个file结构程序
以下代码是不同2个进程打开同一个文件的实验
#include
#include
#include
#include
#include
#include
#include
int main( void )
{
int fd1;
fd1 = open( "test", O_CREAT | O_RDWR );
assert( fd1 != -1 );
write( fd1, "Hello,Pig", 9 );
sleep( 20 );//这里睡秒20秒,主要是为了打开另外一个进程
close( fd1 );
return 0;
}
#include
#include
#include
#include
#include
#include
#include
int main( void )
{
int fd1;
char str[10];
fd1 = open( "test", O_CREAT | O_RDWR );
assert( fd1 != -1 );
read( fd1, str, 9 );
str[9] = '\n';
printf( "%s\n", str );
close( fd1 );
return 0;
}
得出的结果是Hello,pig, 至此,完全证明了在用open打开文件时,如果打开文件的模式相同,则所有的文件描述符都是使用同一file的,所以像什么read,write之类的函数是线程不安全的 因为不可以重入
另外,说点题外话,起始我们用write时,操作的是file结构提供的内核缓冲区,不要以为在用户空间哟~~~~~~~~~
假如真这么做的话,的确很不安全。一般的做法是,第一个打开文件的程序,应该对打开的文件资源上锁,独占写锁,第二个打开的程序,只能读取文件,而不能修改。
我觉得楼主的实验也证明不了你说的东西呀。
比如我问几个问题,看看楼主怎么解释:
1,你说虽然文件描述符不同,但都是指向同一个 file 结构。为什么第一个演示实验中,两次用 fd2 写文件却没有使 fd1 的文件位置后移?(你显然没有用 lseek 回倒)
2,楼主说 file 中只(原话是唯一,我这么理解可以吧)纪录有多少进程在使用本文件。那么像实验一这样,_一个_进程打开了两遍同一个文件。如果我用它返回的不同的文件描述符关闭两次文件,由于系统无法发现这一区别,会不会出现错误?
3,楼主的实验如何说明系统在 read 和 write 的时候使用的缓存?
阅读(687) | 评论(0) | 转发(0) |