execlp如何正常工作?

时间:2016-12-06 05:54:55

标签: unix exec

所以我正在查看我发给他的教授的代码,试图让我们了解如何实现>,<,|支持我们的unix shell。我运行他的代码并对实际发生的事情感到惊讶。

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

这在我当前所在的目录中创建了一个用户列表文件,其中" who"该文件中的数据。我不知道fd和execlp之间的连接在哪里。 execlp是如何设法将信息放入用户列表的? execlp甚至知道用户列表是如何存在的?

3 个答案:

答案 0 :(得分:1)

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

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

最后,您致电execlp(3),致电execve(2)。成功后,将使用新的可执行文件重新启动整个过程(因此为其提供了新的virtual address space),其 stdout 仍然是execve文件描述符。特别是(除非perror失败)who > userlist来电未到达

所以你的代码有点像运行userlist的shell正在做什么;它将 stdout 重定向到who并运行-f命令。

如果您正在编写shell,请使用strace(1) - 特别是strace -f /bin/sh -c ls选项 - 来了解完成了哪些系统调用。还可以尝试bash来查看shell的行为。还要研究现有free software炮弹的源代码(例如sash'if_sub': function(a, b, opts) { if (a.includes(b)) return opts.fn(this); else return opts.inverse(this); } )。

另见this以及我在那里提供的参考资料。

答案 1 :(得分:0)

execlp什么都不知道。在执行stdout之前关闭并打开一个文件,因此描述符是对应于stdout的描述符(打开总是返回最低的空闲描述符)。此时,该过程有一个" stdout"插入文件。然后调用exec并替换为整个地址空间,但是一些属性仍然作为描述符,因此要知道who的代码是使用与文件对应的标准输出执行的。这是重定向由shell管理的方式。

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

答案 2 :(得分:0)

Basile Starynkevitch正确地解释道:

  

close(1);file descriptor 1(STDOUT_FILENO)免费。所以creat("userlist",0644)可能会重复使用它......

这是因为,正如Jean-BaptisteYunès写的那样,“打开总是返回最低的自由描述符”。

应该强调的是,教授的代码只有可能有效;如果文件描述符0关闭,则失败。