2016-12-06 68 views
0

所以我在看着我的教授的代码,他分发给我们一个如何实现的想法>,<,|支持到我们的unix shell。我运行他的代码,并对实际发生的事情感到惊讶。execlp如何正确工作?

if(pid == 0) 
{ 
    close(1);         // close 
    fd = creat("userlist", 0644);    // then open 
    execlp("who", "who", NULL);    // and run 
    perror("execlp"); 
    exit(1); 
} 

这造成了我目前在目录中的用户列表文件,与该文件中的“谁”的数据。我没有看到fd和execlp之间的连接在哪里。 execlp如何设法将信息放入用户列表中? execlp如何知道用户列表存在?

回答

0

阅读Advanced Linux Programming。它有几个与这个问题有关的章节。我们无法用几句话解释所有这些。另请参阅standard streamprocess wikipages。

首先,所有system calls(请参阅syscalls(2)获取列表,并阅读您正在使用的每个单独系统调用的文档)应该针对故障进行测试。但是,假设他们都成功了。在close(1);之后file descriptor 1(STDOUT_FILENO)是免费的。所以creat("userlist",0644)很可能会重新使用它,因此fd是1;您已将标准输出重定向到新行创建的userlist文件。

最后,你打电话execlp(3)这将叫execve(2)。如果成功,则使用新的可执行文件重新启动整个过程(因此新的virtual address space已给出),其标准输出仍然是userlist文件描述符。特别是(除非execve失败)perror呼叫是未达到

所以你的代码有点像运行who > userlist正在运行的shell;它执行stdoutuserlist的重定向并运行who命令。

如果您正在编写一个shell,请使用strace(1) - 与-f选项一起使用 - 以了解完成了哪些系统调用。尝试strace -f /bin/sh -c ls以查看shell的行为。还研究现有的free software炮弹的源代码(例如bashsash)。

另请参阅this和我在那里给出的参考文献。

0

execlp什么都不知道。在执行stdout之前关闭并打开一个文件,因此描述符是与stdout相对应的描述符(打开总是返回最低空闲描述符)。在这一点上,这个过程有一个插在文件中的“stdout”。然后exec被调用,这取代了整个地址空间,但一些属性仍然作为描述符,所以知道who的代码是通过对应于该文件的stdout执行的。这是重定向由shell管理的方式。

请记住,当您使用printf(例如)时,您永远不会指定具体是什么stdout ...可以是文件,终端等。