阻塞非阻塞&fcntl()函数&文件锁&死锁

阻塞非阻塞

产生阻塞的场景,读设备文件,读网络文件(读常规文件不需要阻塞)
/dev/tty–终端文件
阻塞非阻塞是设备文件,网络文件的属性,O_NONBLOCK

fcntl()函数

头文件

#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>

定义

int fcntl(int filedes, int cmd,.../* int arg * / ) ;
//第三个参数可以是long,int, 结构体指针

返回值

成功:依赖于cmd
出错:- 1

参数

  • cmd
  1. 复制现存的文件描述符
    cmd = F_DUPFD
//复制文件描述符,fd和 newfd不相等,但是指向同一个文件表(包含文件状态标志,当前文件位移量,v节点指针)
fd = open("a.txt", O_RDWR);
newfd = fcntl(fd, F_DUPFD, 1);

close(fd)//文件并没有关闭,还有newfd
  1. 获得/设置文件状态标志

获得:cmd = F_GETFL

flag = fcntl(fd, F_GETFL);

示例:

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
// 0000 	O_RDNOLY
// 0001 	O_WRONLY
// 0010 	O_RDWR
// 0011 	O_ACCMODE
// 1000 	O_NONBLOCK
    int fd = open("a.txt", O_RDONLY | O_APPEND | O_NONBLOCK);

    int flag = fcntl(fd ,F_GETFL);
    //O_ACCMODE = 0011, 取flag的后两位
    if ((flag & O_ACCMODE) == O_RDONLY)
    {
        printf("O_RDONLY\n");
    }
    else if ((flag & O_ACCMODE) == O_WRONLY)
    {
        printf("O_WRONLY\n");
    }
    else if ((flag & O_ACCMODE) == O_RDWR)
    {
        printf("O_RDWR\n");
    }

    if (flag & O_APPEND)
    {
        printf("O_APPEND\n");
    }
    if (flag & O_NONBLOCK)
    {
        printf("O_NONBLOCK\n");
    }
    close(fd);
    return 0;
}

    //设置文件标志阻塞为非阻塞
    int flag = fcntl(STDIN_FILENO, F_GETFL);
    flag = flag | NONBLOCK;
    fcntl(STDIN_FILENO, F_SETFL, flag);
  1. 获得/设置记录锁
  • cmd = F_GETLK
  • cmd = F_SETLK//尝试上锁,不阻塞,如果其它进程已经锁住了,无法上锁时,直接返回失败
    如果没有被锁住的话,直接返回上锁成功
  • cmd = F_SETLKW//会阻塞,如果其它进程已经锁住了,无法上锁时,fcntl函数会等待其它进程释放锁为止才返回
  • fcntl的第三个参数此时是指向结构体flock的指针

记录锁

  • 记录锁(record locking)的功能是:一个进程正在读或修改文件的某个部分时,可以阻止其他进程修改同一文件区。
  • 多个进程操作同一个文件要上读写锁
  • struct flock结构体的定义如下:
struct flock {
	short l_type;  /* 记录锁类型,F_RDLCK(共享读锁),F_WRLCK(独占性锁)或F_UNLCK(解锁一个区域) */
	off_t l_start;  /* 起始位置偏移量,单位字节,是相对于l_whence而言 */
	short l_whence; /* SEEK_SET,SEEK_CUR,或SEEK_END */
	off_t l_len; /* 长度,单位字节,值为0时表示一直到文件尾 */
	pid_t l_pid; /* 使用F_GETLK时返回此值 */
}
文件加锁状态是否能上读锁是否能加写锁
无锁
读锁
写锁

文件上锁

    int fd = open("a.txt", O_RDONLY);
    struct flock fl;

    //上读锁
    fl.l_type = F_RDLCK;
    fl.l_start = 0;
    fl.l_whence = SEEK_SET;
    fl.len = 0;
    fcntl(fd, F_SETLKW, &fl);
    
    //解锁
    fl.l_type = F_UNLCK;
    fcntl(fd, F_SETLK, &fl);

死锁

  • 如果两个进程相互等待对方持有并且不释放(锁定)的资源时,则这两个进程就处于死锁状态。
  • 如果一个进程已经控制了文件中的一个加锁区域,然后它又试图对另一个进程控制的区域加锁,则它就会睡眠,在这种情况下,有发生死锁的可能性。
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值