很多情况下开发场景是这样的:
两个程序,分别用用户A,B在跑。A,B之间要使用共享数据,例如共享内存,信号量等,就需要触及权限问题。
一般的处理方法是,A创建的对象,例如命名信号量,需要赋予other一定的读写权限(我们假定A, B不是一个用户组)。
这时候我们假设A里面有这么一段程序
sem_t *pSem = sem_open("Shared-Semaphore-For-A-And-B", O_CREAT, 0606,1);
这里 pSem就对other有了读写权限。至少从程序上来看是这样的。
我们在B中打开这个命名信号量:
sem_t *pSem = sem_open("Shared-Semaphore-For-A-And-B", 0);
if(!pSem)
printf("Open failed");
从代码上看起来都没有什么问题。
但是你会发现运行结果是这个:
Open failed
这是怎么回事?
查看/dev/shm/下面的所有命名信号量产生的临时文件,你会发现
Shared-Semaphore-For-A-And-B -rw----r--
为什么最后的是r,而不是rw?? 我们可明明要求权限是rw -- rw 的
Recall from the UEAP(Unix环境高级编程),里面有一个API被称作umask。
umask是这么一回事:
umask设置进程在创建文件时强制取消的权限。比如umask是002,则other用户的write权限会被强制取消!
我们在用户A的shell上umask一把看看。
0002
嗯,看起来这就是原因了。
原因找到,下面的问题是怎么办?
方法1:通过umask命令每次都修改用户A的umask。 问题:只对当时的shell有效,如果你logout,或者其它人用用户A使用另一个shell登入,则无效。这个明显不是我们要的方法
方法2:修改用户A的配置文件,使得全局umask都被强制修改。 这个属于牵一发而动全身的玩法,不推荐。
方法3:利用umask函数修改用户A程序的umask。这个是个靠谱的玩法,在这个方法下,只有用户A程序的umask被更改了。其它程序仍然使用用户A配置的umask。
实测一下是否能够解决问题:
在A的程序中加入这么一段:
umask(0000); //修改umask
实测后,信号量可以打开了。
结论:如果你要在不同用户间共享东西,最好首先检测一下umask的状况,以免被坑。