C 存在分叉过程和'\n';?

C 存在分叉过程和'\n';?,c,shell,printf,fork,C,Shell,Printf,Fork,我有一个简单的shell程序,可以在交互和非交互模式下工作。我已经尽可能地简化了代码来提出我的问题,但是它仍然有点长,所以很抱歉 #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> /** *main-entry poin

我有一个简单的shell程序,可以在交互和非交互模式下工作。我已经尽可能地简化了代码来提出我的问题,但是它仍然有点长,所以很抱歉

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>


/**
 *main-entry point for gbk
 *Return: returns the index of 0 on sucess
 */
int main(void)
{

    char *cmd = malloc(1 * sizeof(char)), *cmdargs[2];
    size_t cmdlen = 0;
    int childid, len;
    struct stat cmdinfo;

    while (1)
    {
        printf("#cisfun$ ");
        len = getline(&cmd, &cmdlen, stdin);
        if (len == -1)
        {
            free(cmd);
            exit(-1);
        }
        /*replace the ending new line with \0*/
        cmd[len - 1] = '\0';
        cmdargs[0] = cmd;
        cmdargs[1] = NULL;

        childid = fork();
        if (childid == 0)
        {
            if (stat(*cmdargs, &cmdinfo) == 0 && cmdinfo.st_mode & S_IXUSR)
                execve(cmdargs[0], cmdargs, NULL);
            else
                printf("%s: command not found\n", *cmdargs);
            exit(0);
        }
        else
            wait(NULL);
    }
    free(cmd);
    exit(EXIT_SUCCESS);
}
#包括
#包括
#包括
#包括
#包括
#包括
/**
*gbk的主要入口点
*Return:成功返回0的索引
*/
内部主(空)
{
char*cmd=malloc(1*sizeof(char)),*cmdargs[2];
大小\u t cmdlen=0;
int childid,len;
struct stat cmdinfo;
而(1)
{
printf(“#cisfun$”);
len=getline(&cmd,&cmdlen,stdin);
如果(len==-1)
{
免费(cmd);
出口(-1);
}
/*将结束的新行替换为\0*/
cmd[len-1]='\0';
cmdargs[0]=cmd;
cmdargs[1]=NULL;
childid=fork();
if(childid==0)
{
if(stat(*cmdargs,&cmdinfo)==0&&cmdinfo.st\u mode&S\u IXUSR)
execve(cmdargs[0],cmdargs,NULL);
其他的
printf(“%s:找不到命令\n”,*cmdargs);
出口(0);
}
其他的
等待(空);
}
免费(cmd);
退出(退出成功);
}
为了总结此程序的功能,它将首先打印提示符
#cisfun$
,在交互模式下等待输入,并在非交互模式下获取管道值,创建子进程,子进程检查传递的字符串是否为有效的可执行二进制文件,如果是,它以另一种方式执行,打印一条“未找到命令”消息并再次提示

我已经让这个程序在交互模式下的大多数场景下都能正常工作,但是当我在非交互模式下运行它时,各种疯狂(意外)的事情开始发生

例如,当我运行
echo”/bin/ls“|/a.out
,(
a.out
是编译程序的名称) 您首先希望打印
#cisfun$
消息,因为这是while循环中执行的第一件事,然后是
/bin/ls
命令的输出,最后是
#cisfun$
提示符,但实际情况并非如此。下面是发生的情况

  • 非常奇怪的是,
    ls
    命令甚至在第一条打印消息之前就运行了。一、 起初,我们认为有一些
    线程化
    正在进行,并且
    printf
    比执行ls命令的子进程慢。但我不确定这是不是真的,因为我是个笨蛋。而且,如果我在打印一条消息时,在末尾加上
    '\n'
    ,而不仅仅是一个字符串,事情也会变得有点疯狂。(如果我将
    printf(“#cisfun$”)
    更改为
    printf(“#cisfun$\n”)
    ),则会发生以下情况:
  • 它正常工作,因此它让我思考
    '\n'
    fork
    printf
    的速度之间的关系。简言之,对此有何解释

  • 我的第二个问题是,为什么我的程序不执行第一个命令并进入交互模式,我不明白为什么它在打印第二条消息后终止。通过在退出后检查状态代码(255),我意识到其效果与在交互模式下按
    ctr+D
    相同,我认为是通过
    getline
    功能退出的。但是我不明白为什么要在第二个提示符中插入
    EOF

  • 1.输出通常是行缓冲的,这就是为什么添加换行符会使提示出现在ls的输出之前。实际上,请始终在@Peter Thank you之前调用,但很抱歉,您可以对行缓冲的含义稍微友好一点。@EHM:如果有数据可读取,
    getline
    将读取它。如果没有数据,但写入程序仍打开管道,
    getline
    将阻塞,直到有数据为止。如果没有数据且管道的另一端已关闭,
    getline
    表示EOF。我不知道你说的“两个包”是什么意思。@EHM:但这和你在终端上阅读时看到的行为是一样的
    getline
    无法在一次返回中同时返回数据和指示EOF。你必须再打一次电话才能知道EOF已经达到。