linux文件讀寫 文件鎖、select、poll .

一、文件鎖

    文件鎖用於多個用戶共同使用或操作同一個文件。有讀鎖的時候可以再加讀鎖,不能再加寫鎖。有寫鎖的時候,不能加任何鎖,加讀鎖時,該描述符必須是讀打開,加寫鎖時,該描述符必須是寫打開,且只在進程間有用。     

 

 重寫的上鎖方法

  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. }  
//lock.c
int lock_set(int fd,int type){
    struct flock lock;

    lock.l_type=type;
    lock.l_start=0;
    lock.l_whence=SEEK_SET;
    lock.l_len = 0;
    lock.l_pid=-1;

    fcntl(fd,F_GETLK,&lock);
    if(lock.l_type!=F_UNLCK){
        if(lock.l_type == F_RDLCK)
            printf("Read lock already set by %d!\n",lock.l_pid);
        else if(lock.l_type == F_WRLCK)
            printf("Write lock already set by %d!\n",lock.l_pid);
    }
    lock.l_type = type;
    //此處的F_SETLKW爲F_SETLK的阻塞版本,當無法獲取鎖時進入睡眠等待狀態
    if(fcntl(fd,F_SETLKW,&lock)<0){
        printf("Lock failed:type=%d!\n",lock.l_type);
        exit(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("UN lock set by %d\n",getpid());
            break;
        default:
            break;
    }
}


上寫鎖

  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. }  
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include"lock.c"

int main(){
    int fd;
    fd=open("readme",O_RDWR|O_CREAT,0666);
    if(fd<0){
        printf("Open file error\n");
        exit(1);
    }
    lock_set(fd,F_WRLCK);
    getchar();
    lock_set(fd,F_UNLCK);
    getchar();
    return 0;

}


上讀鎖

  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. }  
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include"lock.c"

int main(){
    int fd;
    fd=open("readme",O_RDWR|O_CREAT,0666);
    if(fd<0){
        printf("Open file error\n");
        exit(1);
    }
    lock_set(fd,F_RDLCK);
    getchar();
    lock_set(fd,F_UNLCK);
    getchar();
    return 0;

}

在兩個終端中測試:

兩個終端可以同時加上讀鎖。

有一個終端加上讀鎖,則必須等讀鎖釋放才能加寫鎖。

有一個終端加寫鎖必須釋放才能加別的鎖。

 

二、多路複用:select、poll

  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. }  
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<memory.h>
#define MAX(a,b) (a>b?a:b)

int main(){
    int fd[3];
    char buff[1024];
    int res,max_fd,i,num;
    fd_set insert,temp_insert;
    struct timeval tv;
    fd[0]=0;
    if((fd[1]=open("in1",O_RDONLY|O_NONBLOCK))<0){
        printf("open in1 error!\n");
        return 1;
    }
    if((fd[2]=open("in2",O_RDONLY|O_NONBLOCK))<0){
        printf("open in2 error!\n");
        return 1;
    }
    //選出最大的fd,select()函數用的
    max_fd=MAX(MAX(fd[0],fd[1]),fd[2]);
    //清空fd_set
    FD_ZERO(&insert);
    for(i=0;i<3;i++){
        FD_SET(fd[i],&insert);
    }
    //設置延遲
    tv.tv_sec=60;
    tv.tv_usec=0;

    while(FD_ISSET(fd[0],&insert) || FD_ISSET(fd[1],&insert) || FD_ISSET(fd[2],&insert)){
        temp_insert = insert;
        //select函數會對fd_set產生修改,只保存變化的文件符,所以要用一個temp
        res=select(max_fd+1,&temp_insert,NULL,NULL,&tv);
        switch(res){
            case -1:
                    printf("select error!\n");
                    return 1;
                    break;
            case 0:
                    printf("time out\n");
                    return 1;
                    break;
            default:
                    for(i=0;i<3;i++){
                        if(FD_ISSET(fd[i],&temp_insert)){
                                memset(buff,0,1024);
                                num=read(fd[i],buff,1024);
                                if(num<0){
                                    return 1;
                                }else if(num == 0){
                                    close(fd[i]);
                                    FD_CLR(fd[i],&insert);
                                }else{
                                    if(i == 0){
                                        if((buff[0] == 'q') || (buff[0] == 'Q')){
                                            return 0;
                                        }
                                    }
                                    write(STDOUT_FILENO,buff,num);

                                }
                        }
                    }
            }
    }
}


 

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

 

  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. }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章