linux|进程间通信如何加锁

linux|进程间通信如何加锁,第1张

进程间通信有一种[共享内存]方式,大家有没有想过,这种通信方式中如何解决数据竞争问题?我们可能自然而然的就会想到用锁。但我们平时使用的锁都是用于解决线程间数据竞争问题,貌似没有看到过它用在进程中,那怎么办?

关于进程间的通信方式估计大多数人都知道,这也是常见的面试八股文之一。

个人认为这种面试题没什么意义,无非就是答几个关键词而已,更深入的可能面试官和面试者都不太了解岩凯销。

关于进程间通信方式我之前在【这篇文章】中有过介绍,感兴趣的可以移步去看哈。

进程间通信有一种[共享内存]方式,大家有没有想过,这种通信方式中如何解决数据竞争问题?

我们可能自然而然的就会想到用锁。但我们平时使用的锁都是用于解决线程间数据粗游竞争问题,貌似没有看到过它用在进程中,那怎么办?

我找到了两种方法,信号量和互斥锁。

直接给大家贴代码吧,首先是信号量方式:

代码中的MEOW_DEFER,它内部的函数会在生命周期结束后触发。它的核心函数其实就是下面这四个:

具体含义大家应该看孙禅名字就知道,这里的重点就是sem_init中的pshared参数,该参数为1表示可在进程间共享,为0表示只在进程内部共享。

第二种方式是使用锁,即pthread_mutex_t,可是pthread_mutex不是用作线程间数据竞争的吗,怎么能用在进程间呢?

可以给它配置一个属性,示例代码如下:

它的默认属性是进程内私有,但是如果给它配置成PTHREAD_PROCESS_SHARED,它就可以用在进程间通信中。

相关视频推荐

360度无死角讲解进程管理,调度器的5种实现

Linux进程间通信-信号量、消息队列和共享内存

学习地址:C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂

需要C/C++ Linux服务器架构师学习资料加qun812855908获取(资料包括 C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg 等),免费分享

完整代码如下:

我想这两种方式应该可以满足我们日常开发过程中的大多数需求。

锁的方式介绍完之后,可能很多朋友自然就会想到原子变量,这块我也搜索了一下。但是也不太确定C++标准中的atomic是否在进程间通信中有作用,不过看样子boost中的atomic是可以用在进程间通信中的。

其实在研究这个问题的过程中,还找到了一些很多解决办法,包括:

Disabling Interrupts

Lock Variables

Strict Alternation

Peterson's Solution

The TSL Instruction

Sleep and Wakeup

Semaphores

Mutexes

Monitors

Message Passing

Barriers

这里就不过多介绍啦,大家感兴趣的可以自行查阅资料哈。

flock的选项-n等同于--nonblock,表示谨知非阻塞模式。man flock可以看到详细说明:

Fail (with an exit code of 1) rather than wait if the lock cannot be immediately acquired.

翻译过来就是,若不能立即获得文件锁,就直接出错返回1而不是继续等待(默认flock是会继续等待直到获得文件锁)。

3就是fd(即文件描述符)祥宏消。

文件锁只是用于防止多个程序同时访问一个文件的冲突情况。

Shell自动分配fd的话,原本就不会使用已被占用的fd,而是自动递增。

这里显式指定绝毁fd为3(3<>mylockfile),是为了flock有 *** 作的对象。只有unlock后文件才能被其他程序访问,这样就可以保证文件访问不冲突。

方法锁文件仅仅是充当一个指示器的角色,程序间需要通过相互协作来使用它们。锁文件只是建议性锁,与此对立的是强制性锁。为创建一个用作指示器的文件,我们使用带O_CREATE和O_EXCL标志的open系统调用。这将使我们以一个原子 *** 作同时完成两项工作:确定文件不存在,然后创建它。实现//file : lock.c#i nclude#i nclude#i nclude#i nclude#i ncludeint main(){int file_descint save_errnofile_desc = open(/tmp/LockFile.test, O_RDWR   O_CREAT   O_EXCL, 0444)if (file_desc <0){save_errno = errnoprintf(Open failed with error is %dn, save_errno)}else {printf(Open succeededn)}exit(EXIT_SUCCESS) 陪颤 }第一次运行程序:$ lock输出如下:Open succeeded我们再次运行程序:$ lock输出如下:Open failed with error is 17分析:第一次运行程序时,由于文件并不存在,所以执行成功。对于后续的执行,因为文件已经存在而失败了。若想程序再次执行成功,必须删除锁文件。在Linux系统中,通常错误号磨梁码17代表的是EEXIST,此错误用以表示一个文件已存在。错误号定义在头文件errno.h或(更常见的)它所芦游败包含的头文件中。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/8235547.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-14
下一篇2023-04-14

发表评论

登录后才能评论

评论列表(0条)

    保存