linux文件读写 文件锁、select、poll .

来源:互联网 发布:spss mac安装教程 编辑:程序博客网 时间:2024/06/05 18:48

一、文件锁

    文件锁用于多个用户共同使用或操作同一个文件。有读锁的时候可以再加读锁,不能再加写锁。有写锁的时候,不能加任何锁,加读锁时,该描述符必须是读打开,加写锁时,该描述符必须是写打开,且只在进程间有用。     

 

 重写的上锁方法

[cpp] view plaincopyprint?
  1. //lock.c   
  2. int lock_set(int fd,int type){  
  3.     struct flock lock;  
  4.   
  5.     lock.l_type=type;  
  6.     lock.l_start=0;  
  7.     lock.l_whence=SEEK_SET;  
  8.     lock.l_len = 0;  
  9.     lock.l_pid=-1;  
  10.   
  11.     fcntl(fd,F_GETLK,&lock);  
  12.     if(lock.l_type!=F_UNLCK){  
  13.         if(lock.l_type == F_RDLCK)  
  14.             printf("Read lock already set by %d!\n",lock.l_pid);  
  15.         else if(lock.l_type == F_WRLCK)  
  16.             printf("Write lock already set by %d!\n",lock.l_pid);  
  17.     }  
  18.     lock.l_type = type;  
  19.     //此处的F_SETLKW为F_SETLK的阻塞版本,当无法获取锁时进入睡眠等待状态  
  20.     if(fcntl(fd,F_SETLKW,&lock)<0){  
  21.         printf("Lock failed:type=%d!\n",lock.l_type);  
  22.         exit(1);  
  23.     }  
  24.   
  25.     switch(lock.l_type){  
  26.         case F_RDLCK:  
  27.             printf("read lock set by %d\n",getpid());  
  28.             break;  
  29.         case F_WRLCK:  
  30.             printf("write lock set by %d\n",getpid());  
  31.             break;  
  32.         case F_UNLCK:  
  33.             printf("UN lock set by %d\n",getpid());  
  34.             break;  
  35.         default:  
  36.             break;  
  37.     }  
  38. }  


上写锁

[cpp] view plaincopyprint?
  1. #include<stdio.h>   
  2. #include<fcntl.h>   
  3. #include<unistd.h>   
  4. #include"lock.c"   
  5.   
  6. int main(){  
  7.     int fd;  
  8.     fd=open("readme",O_RDWR|O_CREAT,0666);  
  9.     if(fd<0){  
  10.         printf("Open file error\n");  
  11.         exit(1);  
  12.     }  
  13.     lock_set(fd,F_WRLCK);  
  14.     getchar();  
  15.     lock_set(fd,F_UNLCK);  
  16.     getchar();  
  17.     return 0;  
  18.   
  19. }  


上读锁

[cpp] view plaincopyprint?
  1. #include<stdio.h>   
  2. #include<fcntl.h>   
  3. #include<unistd.h>   
  4. #include"lock.c"   
  5.   
  6. int main(){  
  7.     int fd;  
  8.     fd=open("readme",O_RDWR|O_CREAT,0666);  
  9.     if(fd<0){  
  10.         printf("Open file error\n");  
  11.         exit(1);  
  12.     }  
  13.     lock_set(fd,F_RDLCK);  
  14.     getchar();  
  15.     lock_set(fd,F_UNLCK);  
  16.     getchar();  
  17.     return 0;  
  18.   
  19. }  

在两个终端中测试:

两个终端可以同时加上读锁。

有一个终端加上读锁,则必须等读锁释放才能加写锁。

有一个终端加写锁必须释放才能加别的锁。

 

二、多路复用:select、poll

[cpp] view plaincopyprint?
  1. #include<stdio.h>   
  2. #include<fcntl.h>   
  3. #include<unistd.h>   
  4. #include<memory.h>   
  5. #define MAX(a,b) (a>b?a:b)  
  6.   
  7. int main(){  
  8.     int fd[3];  
  9.     char buff[1024];  
  10.     int res,max_fd,i,num;  
  11.     fd_set insert,temp_insert;  
  12.     struct timeval tv;  
  13.     fd[0]=0;  
  14.     if((fd[1]=open("in1",O_RDONLY|O_NONBLOCK))<0){  
  15.         printf("open in1 error!\n");  
  16.         return 1;  
  17.     }  
  18.     if((fd[2]=open("in2",O_RDONLY|O_NONBLOCK))<0){  
  19.         printf("open in2 error!\n");  
  20.         return 1;  
  21.     }  
  22.     //选出最大的fd,select()函数用的   
  23.     max_fd=MAX(MAX(fd[0],fd[1]),fd[2]);  
  24.     //清空fd_set   
  25.     FD_ZERO(&insert);  
  26.     for(i=0;i<3;i++){  
  27.         FD_SET(fd[i],&insert);  
  28.     }  
  29.     //设置延迟   
  30.     tv.tv_sec=60;  
  31.     tv.tv_usec=0;  
  32.   
  33.     while(FD_ISSET(fd[0],&insert) || FD_ISSET(fd[1],&insert) || FD_ISSET(fd[2],&insert)){  
  34.         temp_insert = insert;  
  35.         //select函数会对fd_set产生修改,只保存变化的文件符,所以要用一个temp  
  36.         res=select(max_fd+1,&temp_insert,NULL,NULL,&tv);  
  37.         switch(res){  
  38.             case -1:  
  39.                     printf("select error!\n");  
  40.                     return 1;  
  41.                     break;  
  42.             case 0:  
  43.                     printf("time out\n");  
  44.                     return 1;  
  45.                     break;  
  46.             default:  
  47.                     for(i=0;i<3;i++){  
  48.                         if(FD_ISSET(fd[i],&temp_insert)){  
  49.                                 memset(buff,0,1024);  
  50.                                 num=read(fd[i],buff,1024);  
  51.                                 if(num<0){  
  52.                                     return 1;  
  53.                                 }else if(num == 0){  
  54.                                     close(fd[i]);  
  55.                                     FD_CLR(fd[i],&insert);  
  56.                                 }else{  
  57.                                     if(i == 0){  
  58.                                         if((buff[0] == 'q') || (buff[0] == 'Q')){  
  59.                                             return 0;  
  60.                                         }  
  61.                                     }  
  62.                                     write(STDOUT_FILENO,buff,num);  
  63.   
  64.                                 }  
  65.                         }  
  66.                     }  
  67.             }  
  68.     }  
  69. }  


 

poll用法与select很相似,只是在一些变量上有些不同:

 

[cpp] view plaincopyprint?
  1. #include <unistd.h>   
  2. #include <fcntl.h>   
  3. #include <time.h>   
  4. #include <stdio.h>   
  5. #include <stdlib.h>   
  6. #include <string.h>   
  7. #include <poll.h>   
  8.   
  9. #define MAX_BUFFER_SIZE 1024  
  10. #define IO_IN_FILES 3   
  11. #define TIME_DELAY 60000   
  12.   
  13. int main() {  
  14.     struct pollfd fds[IO_IN_FILES];  
  15.     char buff[MAX_BUFFER_SIZE];  
  16.     int i,res,real_read;  
  17.   
  18.     fds[0].fd=0;  
  19.     if((fds[1].fd=open("in1",O_RDONLY|O_NONBLOCK))<0) {  
  20.         printf("Open in1 error!\n");  
  21.         return 1;  
  22.     }  
  23.       
  24.     if((fds[2].fd=open("in2",O_RDONLY|O_NONBLOCK))<0) {  
  25.         printf("Open in2 error!\n");  
  26.         return 1;  
  27.     }  
  28.   
  29.     for(i=0;i<IO_IN_FILES;i++)  
  30.         fds[i].events=POLLIN;  
  31.       
  32.     while(fds[0].events||fds[1].events||fds[2].events) {  
  33.         res=poll(fds,IO_IN_FILES,TIME_DELAY);  
  34.   
  35.         switch(res) {  
  36.             case -1:  
  37.                 printf("POLL error!\n");  
  38.                 return 1;  
  39.                 break;  
  40.             case 0:  
  41.                 printf("Time out!\n");  
  42.                 return 1;  
  43.                 break;  
  44.             default:  
  45.                 for(i=0;i<IO_IN_FILES;i++) {  
  46.                     if(fds[i].revents) {  
  47.                         memset(buff,0,MAX_BUFFER_SIZE);  
  48.                         real_read=read(fds[i].fd,buff,MAX_BUFFER_SIZE);  
  49.                         if(real_read<0){  
  50.                             printf("Read error!\n");  
  51.                             return 1;  
  52.                         } else if (real_read==0) {  
  53.                             close(fds[i].fd);  
  54.                             fds[i].events=0;  
  55.                         } else {  
  56.                             if (i==0) {  
  57.                                 if((buff[0]=='q')||(buff[0]=='Q'))  
  58.                                     return 0;  
  59.                             } else {  
  60.                                 write(STDOUT_FILENO, buff,real_read);  
  61.                             //  buff[real_read]='\0';  
  62.                             //  printf("%s",buff);  
  63.                             }  
  64.                         }  
  65.                               
  66.                     }  
  67.   
  68.                 }  
  69.         }  
  70.     }     
  71.       
  72.     return 0;  
  73. }
原创粉丝点击