我写了一个简单的程序:

#include<stdio.h>
#include<unistd.h>
#include <fcntl.h>
#include <stdlib.h>
int main(){
    int fd = open("theFile.txt", O_CREAT | O_RDWR, 0666);
    if(fd<0){
     printf("coudlnt open File descriptor \n");
    }
    pid_t pid = fork();
    if(pid==0){
        dup2(int oldFD, int newFD);
    dup2(fd,1);
        execlp("/bin/ls","ls","-l", NULL);
    }
    return 0;
}

我想要的是,将ls - l的输出重定向到一个名为“the file.txt”的文件。代码按我的预期工作。令我困惑的是dup2参数的顺序。我认为正确的顺序应该是dup2(1, fd)-把fd看作newFD1看作oldFD。但当我使用它作为dup2(fd,1)时,代码就工作了,根据其他一些答案,它基本上是fd的标准输出。
这里的oldFDfd如何,这里的newFD1如何?如果1newFD,为什么这个程序首先工作?
另外,execlp在我调用dup2后覆盖子地址空间。如何将dup2连接到execlp以便获得所需的结果。也就是说,我所做的cat theFile.txt直接列出了电流。
我能在这里得到一些解释吗?

最佳答案

根据[man7]: DUP(2)
int dup2(int oldfd,int newfd);
...
dup()系统调用创建文件描述符oldfd的副本,
使用编号最低的未使用文件描述符
描述符。
...
dup2()系统调用执行与dup()相同的任务,但是
在使用编号最低的未使用文件描述符时,它使用
在newfd中指定的描述符号。如果文件描述符newfd
以前是打开的,在被重新使用之前它是静默关闭的。
当将数据(例如文本)输出到控制台时,应用程序使用stdout流(同样是stderr,但为了简单起见,让我们忽略它)。stdout的fileno为1(最好使用常量而不是值,因为值可能会发生变化-在这种情况下不太可能,但通常情况下):

cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q048923791$ cat /usr/include/unistd.h | grep STDOUT
#define STDOUT_FILENO   1   /* Standard output.  */

在您的子进程中,ls(viaexeclp)将其数据发送到stdout(fileno 1)。在此之前,将进行dup2调用。当前的情况,在调用dup2之前(为了清楚起见,我将在引用stdout的fileno时使用定义的宏):
fd:指向自定义文件(以前打开过)
STDOUT_FILENO:指向标准输出
dup2呼叫:
dup2(fd, STDOUT_FILENO)(现在的情况):关闭当前STDOUT_FILENO,并将fd复制到STDOUT_FILENO。现状:
fd:指向自定义文件
STDOUT_FILENO:指向自定义文件
dup2(STDOUT_FILENO, fd):关闭当前fd并将STDOUT_FILENO复制到fd。现状:
fd:指向标准输出
STDOUT_FILENO:指向标准输出
如图所示,对于#1.,当数据将输出到stdout时,它实际上将转到自定义文件(而不是#2)。即使在使用fd时,它也会转到stdout。
关于第二个问题:
[man7]: EXEC(3)
exec()系列函数替换当前进程映像
一个新的过程图像。本手册中描述的功能
页面是execve(2)的前端。
[man7]: EXECVE(2)
默认情况下,文件描述符在execve()中保持打开状态。
...
POSIX.1说如果文件描述符0、1和2
否则在成功执行execve()后关闭,并且进程
将获得权限,因为设置用户ID或设置组ID模式
在执行的文件上设置了位,然后系统可以打开
未指定这些文件描述符的文件。作为将军
原则上,任何可移植程序,无论是否有特权,都不能
假设这三个文件描述符在
一个execve()。
文件描述符将从子进程传递到ls
下面是您的代码(code.c)的改进版本(仅作细微更改):
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>


int main() {
    int ret = 0, fd = open("thefile.txt", O_CREAT | O_RDWR, 0666);
    if (fd < 0) {
        printf("Coudln't open file: %d\n", errno);
        ret = 1;
    }
    pid_t pid = fork();
    if (pid == 0) {
        // dup2(int oldFD, int newFD);
        if (dup2(fd, STDOUT_FILENO) < 0) {
            printf("Couldn't redirect stdout: %d\n", errno);
            ret = 2;
        }
        execlp("/bin/ls", "ls", "-l", NULL);
    } else if (pid < 0) {
        printf("Couldn't spawn child process: %d\n", errno);
        ret = 3;
    }
    return ret;
}

关于c - dup2参数顺序困惑,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48923791/

10-13 07:27