linux文件读写编程-fcntl()函数
linux I/O编程,用fcntl()函数实现生产者消费者的程序
代码分析
程序分析
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
int lock_set(int fd,int type)
{
struct flock lock;
lock.l_whence= SEEK_SET; //设置当前位置为文件开头
lock.l_start = 0; //加锁区域的偏移量,与l_whence一起决定加锁区域的位置
lock.l_len = 0; //加锁区域的长度
//以上三行的作用是对整个文件加锁
lock.l_type = type; //锁类型
lock.l_pid = -1;
fcntl(fd,F_GETLK,&lock);
if(lock.l_type != F_UNLCK)
{
if(lock.l_type == F_RDLCK)
{ //共享锁,即读锁
printf("Read lock alread set by %d\n",lock.l_pid);
}
else if(lock.l_type == F_WRLCK)
{ //排斥锁,即写锁
printf("Write lock alread set by %d\n",lock.l_pid);
}
}
lock.l_type = type;
if((fcntl(fd,F_SETLKW,&lock)) < 0)
{
printf("Lock failed:type = %d\n",lock.l_type);
return -1;
}
switch(lock.l_type)
{
case F_RDLCK:
{
printf("Read lock set by %d\n",getpid());
}
break;
case F_WRLCK:
{
printf("Write lock set by %d\n",getpid());
}
break;
case F_UNLCK:
{
printf("Release lock by %d\n",getpid());
}
break;
}
return 0;
}
int custum()
{
int fs,fd;
int count;
char c;
if((fs = open("produce.txt",O_RDWR)) < 0)
{
printf("open error\n");
return -1;
}
// if((fd = open("temp.txt",O_RDWR)) < 0)
// {
// printf("open error2\n");
// return -1;
// }
while(1)
{
lock_set(fs,F_WRLCK); //给fs上写锁
lseek(fs,0,SEEK_SET);
// fd=open("temp.txt",O_RDWR|O_CREAT|O_TRUNC,0777);
count=read(fs,&c,1); //返回值是读到的字节数
if(count <= 0)
{
printf("no product!\n");
lock_set(fs,F_UNLCK); //读完了,释放锁
sleep(1); //延迟
continue;
}
printf("get a character: %c \n",c);
lseek(fs,0,SEEK_CUR);
// lseek(fd,0,SEEK_SET);
count = 0;
while(((count = read(fs,&c,1)) == 1) && c!= '\n')
{
printf("read fs: %c\n", c); //这个whlie的作用是复制到temp
write(fd,&c,count);
}
close(fs);
fs = open("produce.txt",O_RDWR|O_TRUNC); //以读写重新打开,删去原程序
lseek(fs,0,SEEK_SET);
lseek(fd,0,SEEK_SET);
while(((count = read(fd,&c,1)) == 1) /*&& c!='\n'*/)
{ //这个while的作用是重新写回
// printf("read fd: %c\n", c);
write(fs,&c,count);
}
unlink("temp.txt"); //关闭文件
close(fd);
lock_set(fs,F_UNLCK);
sleep(2);
}
}
int main(int argc, const char *argv[])
{
custum();
return 0;
}
生产者程序分析 (上锁部分类似,不作新注释)
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
int lock_set(int fd,int type)
{
struct flock lock;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
lock.l_type = type;
lock.l_pid = -1;
fcntl(fd,F_GETLK,&lock);
if(lock.l_type != F_UNLCK)
{
if(lock.l_type == F_RDLCK)
{
printf("Read lock alread set by %d\n",lock.l_pid);
}
else if(lock.l_type == F_WRLCK)
{
printf("Write lock alread set by %d\n",lock.l_pid);
}
}
lock.l_type = type;
if((fcntl(fd,F_SETLKW,&lock)) < 0)
{
printf("Lock failed:type = %d\n",lock.l_type);
return -1;
}
switch(lock.l_type)
{
case F_RDLCK:
{
printf("Read lock set by %d\n",getpid());
}
break;
case F_WRLCK:
{
printf("Write lock set by %d\n",getpid());
}
break;
case F_UNLCK:
{
printf("Release lock by %d\n",getpid());
}
break;
}
return 0;
}
int produce()
{
int fd;
char a='A';
if((fd = open("produce.txt",O_WRONLY|O_APPEND)) < 0) //只读|添加方式打开文件,定位到文件末尾
{
printf("open failed\n");
return -1;
}
while(1)
{
lock_set(fd,F_RDLCK); //此处原来是上写锁,但是只有一对生产者消费者的话,应该是生产者写的时候,消费者不能读,这样的逻辑吧,如有错误还请指正
write(fd,&a,1);
printf("hava produce one character %c \n",a);
a++;
lock_set(fd,F_UNLCK);
sleep(3);
}
close(fd);
}
int main(int argc, const char *argv[])
{
produce();
return 0;
}
执行结果
左:生产者进程;右:消费者进程
事实上,如果把延时(即sleep函数)的值设置为10秒会很清楚地看到是生产者生产了一个字符,下一秒或者说下一时间消费者才会取出这个字符。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 不听话的兔子君!