关于C语言中创建000权限文件可写入及命名信号量权限异常的疑问
关于C语言中创建000权限文件可写入及命名信号量权限异常的疑问
嘿,这个问题问到点子上了——这其实是Unix/Linux权限模型里很容易混淆的细节,咱们一步步掰扯清楚:
为什么000权限的文件能被程序写入?
你对000权限的理解没错:这个权限意味着任何用户(除了root)都不能通过常规方式打开、读取或写入这个文件,但这里有个关键区别:文件权限限制的是「后续的打开操作」,而不是「已经打开的文件描述符的操作」。
咱们看你的代码:
int fd = open("greeting.txt", O_CREAT | O_WRONLY, 0000); write(fd, message, strlen(message));
当你调用open并带上O_CREAT时,内核会做两件事:
- 创建
greeting.txt文件,并且把它的权限设置为你指定的0000(如果你的进程umask是0的话,最终权限就是000;如果umask非0,会和0000做按位与,权限会更严格,但核心逻辑不变)。 - 给当前进程返回一个可写的文件描述符——因为你是这个文件的创建者,并且明确指定了
O_WRONLY,内核会直接赋予这个fd写权限,不需要再检查文件的权限位。
文件的000权限是用来拦「之后想打开这个文件的进程」的——比如你运行完程序后,再用echo "test" > greeting.txt就会报错,但程序里已经拿到的fd,只要没关闭,就能正常调用write,因为内核已经给这个fd开了“绿色通道”,不会再去查文件的权限了。
你可以运行完程序后用ls -l greeting.txt看看,文件权限确实是----------,但里面已经写入了"Hello world"。
为什么000权限的命名信号量能被父子进程修改?
命名信号量的逻辑和文件类似,但有个额外的点:进程的子进程会继承父进程的信号量句柄。
当你用sem_open(sem_name, O_CREAT, 0000, 1)创建信号量时:
- 内核创建信号量对象,权限设置为000,这会阻止其他无关进程打开或访问它。
- 当前进程拿到了这个信号量的合法句柄,内核允许持有者对其执行
sem_post、sem_wait等操作,不管信号量的权限位是什么。 - 父进程fork出的子进程会继承这个信号量句柄——子进程的句柄和父进程的指向同一个内核对象,所以子进程也能直接操作它,不需要再通过权限检查。
简单总结一下:Unix/Linux的权限控制是「进门查票」——在你获取资源(打开文件、创建信号量)的那一刻检查权限,一旦拿到合法的句柄,后续操作就不再受资源权限位的限制了。权限位是用来拦外部无关进程的,已经拿到“入场券”的进程(包括它的子进程)自然可以正常操作。
备注:内容来源于stack exchange,提问作者Amirreza A.
相关产品推荐
相关产品推荐

