Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 无法读取fork之后子项中的stdin?_C_Shell_Fork - Fatal编程技术网

C 无法读取fork之后子项中的stdin?

C 无法读取fork之后子项中的stdin?,c,shell,fork,C,Shell,Fork,一个常规的C程序,是一些shell程序的实现,它使用标准输入获取命令并执行它们,其中main()声明为:int main(int argc,char*argv[]),正常工作。 这是一个小的shell程序,它打印一个提示并在循环中等待用户输入,然后执行输入的命令。但是,我希望在调用时使命令行参数不可见,如下所示: 将main()函数重命名为old_main() 创建一个新的main()函数: 将argv[]字符串数组复制到新数组,然后 删除原始argv[]结构 分叉自身,并在子进程中使用保存

一个常规的C程序,是一些shell程序的实现,它使用标准输入获取命令并执行它们,其中main()声明为:int main(int argc,char*argv[]),正常工作。 这是一个小的shell程序,它打印一个提示并在循环中等待用户输入,然后执行输入的命令。但是,我希望在调用时使命令行参数不可见,如下所示:

  • 将main()函数重命名为old_main()
  • 创建一个新的main()函数:
    • 将argv[]字符串数组复制到新数组,然后
    • 删除原始argv[]结构
    • 分叉自身,并在子进程中使用保存的命令行参数调用old_main,然后退出父进程
它的工作原理是“ps-ef”现在显示命令运行,而不显示命令行参数。 但是,程序现在的行为有所不同,不再等待用户输入,而是继续打印提示。即使Ctrl-C也不再工作了

但是,如果我将该程序称为:

$ echo quit | ./newprog 
命令'quit'被执行(导致程序退出),因此当stdin被重定向时程序仍然工作,但在交互模式下不工作

下面是分叉的新程序,在子程序中使用保存的命令行参数调用旧的main

/* newprog.c */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define MAX_NARGS   40

extern int old_main(int nargc, char *nargv[]);    

int main(int argc, char *argv[])
{
    int i; pid_t pid;
    int nargc=argc;
    char *nargv[];
    nargv[0]=argv[0];

    for (i = 1; i < argc; i++)
    {
        nargv[i]=strdup(argv[i]);
        memset(argv[i],0,strlen(argv[i]));
    }
    nargv[i]=NULL;

    pid=fork();

    if (pid == 0)   return old_main(nargc, nargv); /* child calls old_main() */
    else if (pid == -1) printf("error: fork()\n");
    exit(0);  /* exit parent */
}
/*newprog.c*/
#包括
#包括
#包括
#包括
#定义最大值40
旧城区外部(内部nargc,字符*nargv[]);
int main(int argc,char*argv[])
{
int i;pid_t pid;
int nargc=argc;
char*nargv[];
nargv[0]=argv[0];
对于(i=1;i
我无意中发现,对于我原来的问题(不在进程列表中显示命令行参数),我不必执行fork,这里介绍的方法是将旧的命令行参数复制到新变量,然后删除旧的命令行参数,这在原始的主函数中起作用。但这个问题只解决了一个问题,即在子程序中fork()之后,标准输入似乎不再像原始程序中那样起作用。仍然有兴趣知道这是什么原因。父进程是shell的子进程。在执行命令之前,shell很可能会设置到父stdin的重定向。退出父级时,重定向将终止。孩子的stdin不再监听任何东西。这是关于这个问题的相关阅读,可能是值得复制的@StoryTeller:我假设(fork()的文档化特性-参见man 2 fork)孩子继承openfiles的父文件描述符,通常包括stdin、stdout和stderr,所以即使父文件退出,孩子也应该能够像往常一样读取stdin和写入stdout。在我的例子中,我发现子对象在父对象退出后调用的fgets()中的输入不会等待用户输入,但是,如果我使用shell重定向,则该输入会通过子对象的fgets,并正常工作。为什么会有这种行为差异?man 2 fork:“子对象继承父对象的一组打开文件描述符的副本。子对象中的每个文件描述符都引用相同的打开文件描述(参见打开(2))作为父级中相应的文件描述符。这意味着这两个描述符共享打开的文件状态标志、当前文件偏移量和信号驱动的I/O属性(请参阅fcntl(2)中的F_SETOWN和F_SETSIG说明)。“问题不在于复制文件描述符。问题在于有人在流中写入父级和子级侦听。使用管道命令时,子管道描述符足以保持管道打开。但这与shell从终端转发输入不同。只要父节点还活着,它就会转发,因为这是它等待的唯一PID。