linux 使用fcntl函数为文件添加锁

来源:互联网 发布:人工智能进入国考试卷 编辑:程序博客网 时间:2024/06/18 10:07
#include<sys/types.h> 
#include<sys/stat.h> 
#include<unistd.h> 
#include<fcntl.h> 
#include<stdio.h> 
#include<stdlib.h> 
#include<errno.h> 
#include<string.h> 

#define ERR_EXIT(m) \ 
     do { \ 

        perror(m); \ 

printf("\n");\

        exit(EXIT_FAILURE); \ 
    }  while0


int main( int argc,  char *argv[]) 

     int fd; 

     char const path[] = "/home/fengfulee/lock.txt";

     int flag = O_CREAT|O_RDWR|O_TRUNC;/*这个表示文件打开的方式,没有则创建,并且以读写方式打开,打开后将文件长度设置为0,之前文件如果有内容的话将会丢失.*/

     mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;/*这个表示文件的权限为如果创建文件,其权限为0644*/

      

    fd = open(path,flag,mode); 
     if (fd == - 1) //表示文件打开失败.
        ERR_EXIT( "open error"); 
     /* 只有对文件有相应的读写权限才能施加对应的文件锁 */ 
     struct flock lock; //文件锁的结构体.
    memset(&lock,  0,  sizeof(lock)); 
    lock.l_type = F_WRLCK;  // 排他锁,即不允许其他进程再对其加任何类型的锁,但读锁(共享锁)允许
    lock.l_whence = SEEK_SET; 
    lock.l_start =  0;  //从文件开头开始锁定

    lock.l_len =  0;  // 文件全部内容锁住

    lock.l_pid = getpid(); //将锁定进程的pid设置进去.


     if (fcntl(fd, F_SETLK, &lock) ==  0
    { 
         /* 若为F_SETLKW,这时如果锁已经被其他进程占用,则此进程会阻塞直到其他进程释放锁*/ 
        printf( "lock success\n"); 
        printf( "press any key to unlock\n"); 
        getchar(); 
        lock.l_type = F_UNLCK; 
         if (fcntl(fd, F_SETLK, &lock) ==  0
            printf( "unlock success\n"); 
         else 
            ERR_EXIT( "unlock fail"); 
    } 

     else {

printf("the file was locked by %d\n",lock.l_pid);

        ERR_EXIT( "lock fail"); 

    }


     return  0;  //进程退出会对所有文件解锁

}

编译之后,运行.暂时不要按下任何key.

重新打开一个终端,再次运行这个程序,屏幕上就会显示出:

the file was locked by 3246

lock error:Resource temporarily unavailable


好了,文件锁已经设置完毕了.下面顺便介绍一些基本的知识点.

fcntl -- manipulate file descriptor  操作文件描述符

表头文件
#include<unistd.h>
#include<fcntl.h>
定义函数
int fcntl(int fd , int cmd);
int fcntl(int fd,int cmd,long arg);
int fcntl(int fd,int cmd,struct flock * lock);

这里的第一个参数就是文件描述符,第二个参数表示你要对这个文件描述符或者文件描述符指定的文件要做的事.

可能会有第三个参数,表示如果对文件进行锁定和解锁的结构体变量指针.

其中第二个参数会有很多的类型.

F_DUPFD:用来查找大于或等于参数arg的最小且仍未使用的文件描述词,并且复制参数fd的文件描述词。执行成功则返回新复制的文件描述词。请参考dup2()。

这里和我之前写过的一篇文章中关于linux dup,dup2,dup3 复制一个文件描述符中讲述的在复制文件描述符时的一些规定吧.

   F_GETFD:取得close-on-exec旗标。若此旗标的FD_CLOEXEC位为0,代表在调用exec()相关函数时文件将不会关闭。参考linux dup,dup2,dup3 复制一个文件描述符
    F_SETFD: 设置close-on-exec 旗标。该旗标以参数arg 的FD_CLOEXEC位决定。参考linux dup,dup2,dup3 复制一个文件描述符
    F_GETFL: 取得文件描述词状态旗标,此旗标为open()的参数flags。
    F_SETFL: 设置文件描述词状态旗标,参数arg为新旗标,但只允许O_APPEND、O_NONBLOCK和O_ASYNC位的改变,其他位的改变将不受影响。
    F_GETLK: 取得文件锁定的状态。
    F_SETLK: 设置文件锁定的状态。此时flcok 结构的l_type 值必须是

    F_RDLCK 读锁

    F_WRLCK 写锁

    F_UNLCK 解锁

。如果无法建立锁定,则返回-1,错误代码为EACCES 或EAGAIN。
    F_SETLKW: 和F_SETLK作用相同,但是无法建立锁定时,此调用会一直等到锁定动作成功为止。若在等待锁定的过程中被信号中断时,会立即返回-1,错误代码为EINTR。

当然第三个参数就是我们的flock lock结构体指针了.

struct flcok
{
short int l_type; /* 锁定的状态*/
short int l_whence;/*决定l_start位置*/
off_t l_start; /*锁定区域的开头位置*/
off_t l_len; /*锁定区域的大小*/
pid_t l_pid; /*锁定动作的进程*/
};
    l_type 有三种状态:
    F_RDLCK 建立一个供读取用的锁定
    F_WRLCK 建立一个供写入用的锁定
    F_UNLCK 删除之前建立的锁定
    l_whence 也有三种方式:
    SEEK_SET 以文件开头为锁定的起始位置。
    SEEK_CUR 以目前文件读写位置为锁定的起始位置
    SEEK_END 以文件结尾为锁定的起始位置。

这样通过设置锁定.

哎,好吧.我错了.有些下划线在前台显示不出来.大家自己斟酌查看吧...权当提高自己哈.


0 0