lockf()实现的进程互斥

 Linux中的进程实现互斥有许多方法,比如更改了attr的pthread_mutex_t。这里只说调用lockf()实现的方法。考虑这样的代码:

int main(){

    int ind;

    while((ind = fork()) == -1){}

    if(ind){

        // lockf(1, F_LOCK, 0);    // 注释一

        for(int i=0;i<1000;i++)printf("+%03d ", i);

        // lockf(1, F_ULOCK, 0);    // 注释二

    }

    else

    {

        // lockf(1, F_LOCK, 0);    // 注释三

        for(int i=0;i<1000;i++)printf("-%03d ", i);

        // lockf(1, F_ULOCK, 0);    // 注释四

    }

    return 0;

}

  • 如果4个注释都不拿掉,则结果中正负数交替输出,共享资源stdout(fd为1)没有实现两个进程互斥访问;
  • 如果仅拿掉注释1和2,或者3和4,结果大致与上面的一样,同样是正负数交替输出;
  • 如果把注释全部拿掉,结果中先输出全部正数,再输出全部负数,或者顺序相反,但实现了stdout的进程间互斥访问;

原本推测第二种和第三种的现象应该差不多,即使不是全部进程都对stdout上锁,结果也应该是互斥的。因为没有具体地学习过linux的进程管理知识,只能猜后面的机制。一些文章介绍过struct file_lock,里面有一个锁拥有者的标识、一个等待锁的进程标识队列,可能是linux在实现不是内核的强制锁比如lockf这种锁的时候,是依靠锁的等待队列来调度进程的。调用了lockf的进程,要么获得锁,要么进了等待队列。而没有调用lockf但是用了共享资源的进程,因为不在等待队列里,在进程调度上和获得锁的进程一样,CPU的时间片到了就能用资源,不像等待队列里的即使来了CPU时间片也要放弃,继续等待直至移出队列。这样就可能发生没锁全部进程就和不锁全部的结果差不多了。最后表面,要实现进程互斥,还是要把使用共享资源的全部进程都显式地调用lockf加锁。

还有要注意的是,如果两个进程打印循环的次数不多,现象的区别也不会明显。比如各打印5次,三种方式的结果都差不多。要循环打印的时间足够长才能体现另一个进程等待锁的状态。

参考:狼烟 / Linux内核源码分析:文件锁 (hongxiaolong.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值