Solaris下fcntl加锁后exec调用nano未触发锁等待问题咨询
问题分析与解答
你遇到的这个问题,核心原因有两个,咱们一步步拆解清楚:
1. Nano 并不会复用父进程的已加锁文件描述符,而是重新打开文件
你的程序里,父进程通过open()拿到文件描述符fd,然后给这个fd加了锁,接着调用execlp()启动nano。但nano本身的逻辑是接收文件名参数,然后自己重新打开这个文件——它根本不会去用父进程继承过来的那个已经加了锁的fd。
也就是说,父进程的锁只绑定在自己打开的那个fd上,nano启动后重新打开的是一个全新的文件描述符,这个新fd上没有任何锁。而且nano的代码里完全没有调用fcntl()去检查或获取文件锁的逻辑,所以它对其他进程持有的锁完全“视而不见”,自然能正常打开文件。
2. 建议锁与强制锁的生效条件你可能没配置到位
关于建议锁
默认情况下,fcntl()的文件锁是建议性锁,它的核心规则是:只有所有访问文件的进程都主动去检查并遵守锁的规则时,锁才会生效。如果某个进程(比如nano)根本不做锁的检查,那建议锁对它完全没有约束力——这就是为什么你看到另一个会话的nano依然能打开文件的直接原因。
关于强制锁
你说强制锁和建议锁效果一致,大概率是因为没满足强制锁的生效前提:
- 首先,你的文件系统必须挂载时启用了强制锁选项,比如Linux下需要执行
mount -o mand /your/filesystem(不同系统可能有细微差异); - 其次,目标文件的权限必须设置为
g+s且移除组执行权限,也就是执行chmod g+s,g-x your_target_file——这是告诉内核,这个文件要启用强制锁机制; - 只有同时满足这两个条件后,内核才会强制阻止任何试图打开持有冲突锁文件的进程(不管进程有没有主动检查锁)。如果这两个条件没满足,强制锁其实和建议锁没区别。
验证思路
如果你想验证锁本身是有效的,可以做个小测试:
- 写一个简单的测试程序,它打开目标文件后,调用
fcntl()用F_GETLK检查锁,如果发现有冲突锁就进入等待; - 先运行你原来的程序(把
execlp()换成sleep(30),让锁保持一段时间),然后运行这个测试程序,你会发现测试程序会进入等待状态——这说明锁本身是生效的,只是nano不遵守锁规则而已。
内容的提问来源于stack exchange,提问作者Qwerty
相关产品推荐
相关产品推荐

