fcntl()记录锁

fcntl()函数实现记录锁,在文章http://blog.csdn.net/anonymalias/article/details/9197641讲解得十分详细。
这里我记录的是一些简单的概念及其使用,以后若用到,再回来深究。

1. fcntl()函数的4个常用功能

这里写图片描述
以上是fcntl()函数的常用功能,使用代码基本在http://blog.csdn.net/qq_29344757/article/details/71083191讲解。

2. 记录锁

2.1 函数接口

记录锁也是fcntl()常用功能,cmd取值有:

cmd = F_GETLK: 测试能否建立一把锁
cmd = F_SETLK: 设置锁
cmd = F_SETLKW: 阻塞设置一把锁

fcntl()函数的第3个参数为struct flock结构体类型变量,原型为:

struct flock {
    short   l_type;             //锁的类型,取值为F_RDLCK(共享读锁)、F_WRLCK(独占写锁)、F_UNLCK
    short   l_whence;           //加锁的起始位置,取值为SEEK_SET、SEEK_CUR、SEEK_END
    __kernel_off_t  l_start;    //加锁的起始偏移
    __kernel_off_t  l_len;      //上锁的字节数,为0表示从偏移处一直到文件末尾
    __kernel_pid_t  l_pid;      //已经占用锁的PID(只对F_GETLK命令有效)
    __ARCH_FLOCK_PAD
};

1) F_SETLK: 获取(l_type = F_RDLCK或者F_WRLCK)、释放(l_type = F_UNLCK)由flock结构体所描述的锁。若无法获取锁时,该函数会立即返回错误而不发生阻塞。
2) F_SETLKW: 与F_SETLKW的区别在于,无法操作锁的时候,发生阻塞
3) F_GETLK: 检测是否已经有某个锁已存在调用进程中,如果没有该锁,lock所指向的flock结构体l_type成员就会被置为F_UNLCK,否则已存在的锁的信息将会写入lock所指向的flock结构中

2.2 规则说明

记录锁相当于读写锁的一种扩展类型,在多进程中,记录锁和读写锁一样具有两种锁:共享读锁(F_RDLCK)、独占写锁(F_WRLCK)
1) 共享锁: 文件在给定字节区间,多个进程可以有一把共享读锁,那么允许多个进程以读方式访问该字节区间
2) 独占锁: 文件在给定字节区间,只能有一个进程有一把独占写锁,那么只允许有一个进程以写方式访问该字节区间。
3) 另外,文件在给定的字节区间,若有一把或多把读锁,不能在该字节区再加读写锁,同理,若有一把写锁,就不能在该字节区间再加任何读写锁

如果是在一个进程中对一个文件区间已经加了一把锁,后来该进程中又试图在同一文件区间再加一把锁,那么新锁会覆盖老锁。

测试代码: (摘自《Linux高级程序设计-第3版》P117)

进程2:

// 进程1
struct flock* file_lock(short type, short whence)
{
    static struct flock ret;

    ret.l_type = type;          //锁的类型: 共享读锁(F_RDLCK)、独占写锁(F_WRLCK)、不锁(F_UNLCK)
    ret.l_whence = whence;      //加锁的起始位置
    ret.l_start = 0;            //加锁的起始偏移
    ret.l_len = 0;              //加锁的区域长度(字节),0表示一直到末尾
    ret.l_pid = getpid();

    return &ret;
}

int main(int argc, char *argv[])
{
    int fd;
    int i;
    time_t now;

    fd = open("./tmp.file", O_WRONLY | O_APPEND);
    if (fd < 0)
    {
        perror("open");
        return -1;
    }

    for (i = 0; i < 1000; i++)
    {
        //阻塞设置独占写锁
        fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
        time(&now);
        printf("%s\t%s F_SETLKW lock file %s for 5s\n", ctime(&now), argv[0], "tmp.file");
        char buf[1024] = {};
        sprintf(buf, "hello world %d\n", i);
        int len = strlen(buf);
        if (write(fd, buf, len))
            printf("%s\t%s write file sccess\n", ctime(&now), argv[0], "tmp.file");

        sleep(5);

        //阻塞设置解锁
        fcntl(fd, F_SETLKW, file_lock(F_UNLCK, SEEK_SET));
        sleep(1);       
    }
    close(fd);

    return 0;
}

进程2:

struct flock* file_lock(short type, short whence)
{
    static struct flock ret;

    ret.l_type = type;          //锁的类型: 共享读锁(F_RDLCK)、独占写锁(F_WRLCK)、不锁(F_UNLCK)
    ret.l_whence = whence;      //加锁的起始位置
    ret.l_start = 0;            //加锁的起始偏移
    ret.l_len = 0;              //加锁的区域长度(字节),0表示一直到末尾
    ret.l_pid = getpid();

    return &ret;
}

int main(int argc, char *argv[])
{
    int fd;
    int i;
    time_t now;

    fd = open("./tmp.file", O_WRONLY | O_APPEND);
    if (fd < 0)
    {
        perror("open");
        return -1;
    }

    for (i = 0; i < 1000; i++)
    {
        //阻塞设置独占写锁
        fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
        time(&now);
        printf("%s\t%s F_SETLKW lock file %s for 3s\n", ctime(&now), argv[0], "tmp.file");
        char buf[1024] = {};
        sprintf(buf, "china %d\n", i);
        int len = strlen(buf);
        if (write(fd, buf, len))
            printf("%s\t%s write file sccess\n", ctime(&now), argv[0], "tmp.file");

        sleep(3);

        //阻塞设置解锁
        fcntl(fd, F_SETLKW, file_lock(F_UNLCK, SEEK_SET));
        sleep(1);       
    }
    close(fd);

    return 0;
}

运行结果:
进程1
这里写图片描述
进程2
这里写图片描述
tmp.file的文件内容为:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux中的fcntl是一个系统调用函数,用于对文件描述符进行控制操作。它可以实现文件定、非阻塞I/O、修改文件状态标志等功能。fcntl函数可以在多线程和多进程环境下使用,是Linux系统中非常重要的一个函数。 ### 回答2: fcntl是一个系统调用函数,用于对文件描述符进行管理和操作。它可以实现文件的获取、修改和设置等操作,可以用于改变文件的属性、非阻塞I/O、文件等。 在Linux中,fcntl函数主要有以下几个常用的功能: 1. 复制文件描述符:通过fcntl可以复制一个文件描述符,并返回一个新的文件描述符。这个功能可以在多线程和多进程的编程中使用,以便同时对同一个文件进行操作。 2. 设置文件描述符标志:fcntl函数可以用来设置文件描述符的标志,如设置O_NONBLOCK标志,即实现非阻塞I/O操作。这在异步I/O和事件驱动编程中非常常见,可以提高程序的性能和响应速度。 3. 获取和设置文件状态标志:通过fcntl函数可以获取和设置文件的状态标志,如是否为非阻塞模式、是否为追加模式等。这些标志可以决定文件的默认行为和特性。 4. 获取和设置文件fcntl函数可以获取和设置文件,用于实现多进程或多线程对同一个文件的互斥访问。通过文件可以保证对文件的操作的原子性和互斥性。 总之,fcntl函数在Linux中是一个非常重要和有用的系统调用函数,可以实现对文件描述符的管理和操作。它可以用于复制文件描述符、设置文件描述符标志、获取和设置文件状态标志以及实现文件等功能,提供了对文件的灵活和全面控制。 ### 回答3: fcntl是Linux系统中的一个系统调用,用于对文件描述符进行控制操作。它可以实现多种功能,如设置、获取和修改文件描述符的属性。 fcntl函数接受三个参数:fd(文件描述符),cmd(控制命令)和arg(可选参数)。 - fd:要控制的文件描述符,可以是打开文件、socket连接或其他类似对象的文件描述符。 - cmd:控制命令,用于指定对文件描述符进行的具体操作,例如设置文件描述符为非阻塞模式、获取文件状态标志等。 - arg:可选参数,用于一些特定控制命令的参数传递。 fcntl函数的一些常用控制命令包括: - F_DUPFD:复制文件描述符,并返回一个新的文件描述符。 - F_GETFL:获取文件状态标志。 - F_SETFL:设置文件状态标志。 - F_GETLK:获取文件记录。 - F_SETLK:设置文件记录。 - F_SETLKW:设置文件记录,如果不能立即获取则等待。 fcntl函数的具体使用方式和行为取决于传入的控制命令和参数。例如,通过设置cmd为F_SETFL,可以修改文件描述符的状态标志,如设置为非阻塞模式,从而实现非阻塞I/O操作。而通过设置cmd为F_GETLK,可以获取文件描述符的记录信息。 总结来说,fcntl是Linux系统中用于控制文件描述符的系统调用,通过不同的控制命令实现文件描述符的各种操作,包括设置属性、获取状态、设置等。在Linux开发中,fcntl函数常用于实现对文件和网络连接的高级控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值