我在遗留项目中看到了以下代码模式:
检查是否使用名称“/ abc”创build了共享内存:
int fd = shm_open("/abc", O_RDWR, 0777); if(fd != -1) { close(fd); return -1; }
删除以前由shm_open()
创build的对象:
shm_unlink("/abc");
创build一个共享内存对象:
fd = shm_open("/abc", (O_CREAT | O_RDWR), S_IWUSR);
代码可以运行到步骤2,因为共享内存对象不存在“/ abc”。 换句话说,如果对象确实存在,代码就会返回。 为什么我们应该明确地调用shm_unlink去除不存在的对象?
我认为我们可以按照以下步骤进行操作,我们使用标志O_EXCL
来检查是否存在一个旧的内存对象,如果它不存在,就创build它。 shm_open()
手册页说:
O_EXCL
如果还指定了O
_CREAT
,并且具有给定名称的共享内存对象已经存在,则返回错误。 对象的存在检查,如果它不存在,它的创build是自动执行的。
所以应该可以用一行代替上面所有的代码:
int fd = shm_open("/abc", O_RDWR | O_EXCL, 0777);
那是对的吗?
第2步是多余的吗?
它是。 它没有任何用处。
除此之外,“检查存在”也容易出现TOCTOU漏洞。
我们能否一步缩短上述三步
是。 这是正确的方式去做。 但是你也需要O_CREAT
标志(在你的代码中缺少)。