打开伪终端的主部分后
int fd_pseudo_term_master = open("/dev/ptmx",O_RDWR);
有/dev/pts/[NUMBER]
创建的文件,代表slave
他伪终端的部分。
像我这样无知的人可能会想象,做完ptsname(fd_pseudo_term_master,filename_pseudo_term_slave,buflen);
一个人就应该简单地
做int fd_pseudo_term_slave = open(filename_pseudo_term_slave,O_RDWR);
和做好。
但是,必须有一个非常重要的“锁定”伪终端从属用例,因为为了使事情简单,在进行open
调用之前,必须使用man 3 unlockpt来“解锁”。
我无法找出这个用例是什么?伪终端初始锁定需要什么?代码实现了什么(取自 libc)
/* Unlock the slave pseudo terminal associated with the master pseudo
terminal specified by FD. */
int
unlockpt (int fd)
{
#ifdef TIOCSPTLCK
int save_errno = errno;
int unlock = 0;
if (ioctl (fd, TIOCSPTLCK, &unlock))
{
if (errno == EINVAL)
{
errno = save_errno;
return 0;
}
else
return -1; …
Run Code Online (Sandbox Code Playgroud) 假设我在 pathname 中有一些非目录(文件,命名管道/套接字,等等),在 pathname 中/tmp/foo
有一些其他非目录/tmp/bar
。然后两个(或更多)进程开始并发执行:
流程一:
unlink('/tmp/foo') /* or rename('/tmp/foo', '/tmp/removed') */
unlink('/tmp/bar') /* or rename('/tmp/bar', '/tmp/removed') */
Run Code Online (Sandbox Code Playgroud)
进程二(依此类推)执行以下操作:
link('/tmp/foo', '/tmp/bar')
Run Code Online (Sandbox Code Playgroud)
据我了解,进程二不可能成功(要么link(2)
尝试而/tmp/foo
仍然存在,在这种情况下/tmp/bar
也存在所以它必须失败EEXIST
,或者/tmp/foo
消失所以必须失败ENOENT
)。
但是这种直觉依赖于假设unlink(2)
和/或rename(2)
系统调用在它们的解链效果中本质上是顺序的,所以我正在寻找我的理解的验证:是否有任何类似 *nix 的系统,其内核允许两个unlink(2)
和/或rename(2)
调用成功,但同时会导致link(2)
成功以及(无论是由于重新排序的取消链接/tmp/foo
和/tmp/bar
,而不是抽象/隐藏,从过程调用link(2)
,或通过通过一些其他古怪的竞争状态/错误)?
我已阅读联机帮助页unlink(2)
,rename(2)
以及link(2)
Linux和一些BSD系统,并为这些功能的POSIX规范。但经过仔细考虑,我认为它们实际上没有包含任何关于此事的令人放心的内容。至少rename(2)
,我们承诺如果目标已经存在(操作系统本身的错误除外),则它会被原子替换,但没有别的。
我已经看到声称多个同时执行的rename(foo, qux)
will 原子地和可移植地除了一个重命名之外都失败了ENOENT …