2

我想编写一个程序来创建一个新进程,并且在该子进程中,它应该执行命令:ls。与此同时,父母应该等待孩子死去。但是,我的代码不起作用。

请帮帮我,非常感谢!

int main()
{
    char * read;
    size_t size;

    getline(&read , &size , stdin);
    read[strlen(read)-1] = '\0';
    printf("%s\n" , read);
    int status;
    pid_t f;
    if((f = fork()) == 0)   
    {
        execvp(read , &read);
        exit(0);
    }
    else
    {   
        wait(&status);
    }       
}
4

3 回答 3

3

man execvp

execv()、execvp() 和 execvpe() 函数提供了一个指向以 null 结尾的字符串的指针数组,这些字符串表示新程序可用的参数列表。按照惯例,第一个参数应该指向与正在执行的文件关联的文件名。指针数组必须以 NULL 指针终止。

您需要使用一个数组char*并将最后一个元素设置为NULL.

我不确定getline()正在阅读什么,但我猜它是要lsd 的目录。第一个参数execvp()应该是ls,第二个参数是数组char*

于 2012-09-27T16:38:30.083 回答
1

考虑以下:

#define  _GNU_SOURCE
#define  _POSIX_C_SOURCE 200809L

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

int main(int argc, char *argv[])
{
    char   *input_arg[2];
    char   *input_str = NULL;
    size_t  input_len = 0;
    char  **args;
    ssize_t len;
    size_t  n;
    pid_t   child, p;
    int     status;

    if (argc < 2) {

        /* No command line parameters. Read command from stdin. */
        len = getline(&input_str, &input_len, stdin);

        /* Find length excluding the newline at end. */
        if (len > (ssize_t)0)
            n = strcspn(input_str, "\r\n");
        else
            n = 0;

        if (n > (size_t)0) {

            /* Terminate input command before the newline. */
            input_str[n] = '\0';

        } else {

            fprintf(stderr, "No input, no command.\n");
            return 1;
        }

        input_arg[0] = input_str;
        input_arg[1] = NULL;
        args = input_arg;

    } else {

        /* Use command line parameters */
        argv[argc] = NULL;
        args = argv + 1;
    }

    child = fork();
    if (child == (pid_t)-1) {
        fprintf(stderr, "Cannot fork: %s.\n", strerror(errno));
        return 1;
    }

    if (!child) {
        /* This is the child process. */

        errno = ENOENT;
        execvp(args[0], args);

        fprintf(stderr, "%s: %s.\n", args[0], strerror(errno));
        exit(127);
    }

    do {
        p = waitpid(child, &status, 0);
    } while (p == (pid_t)-1 && errno == EINTR);
    if (p == (pid_t)-1) {
        fprintf(stderr, "Lost child process: %s.\n", strerror(errno));
        return 127;

    }
    if (p != child) {
        fprintf(stderr, "waitpid() library bug occurred.\n");
        return 127;

    }

    if (WIFEXITED(status)) {
       if (!WEXITSTATUS(status))
           fprintf(stderr, "Command successful.\n");
       else
           fprintf(stderr, "Command failed with exit status %d.\n", WEXITSTATUS(status));
       return WEXITSTATUS(status);
    }

    if (WIFSIGNALED(status)) {
        fprintf(stderr, "Command died by signal %s.\n", strsignal(WTERMSIG(status)));
        return 126;
    }

    fprintf(stderr, "Command died from unknown causes.\n");
    return 125;
}

如果指定,上面使用命令行参数,否则它从标准输入中读取一个。由于标准输入未标记化,因此您只能提供命令名称,不能提供参数。如果将input_arg[]数组放大为

    char   *input_arg[4];

并将分配修改为

    input_arg[0] = "/bin/sh";
    input_arg[1] = "-c";
    input_arg[2] = input_str;
    input_arg[3] = NULL;
    args = input_arg;

然后输入字符串将使用/bin/shshell 处理,就像popen()做的那样。

您还可以使用len = getdelim(&input_str, &input_len, '\0', stdin);和删除input_str[n] = '\0';分配以允许多行输入;只要它足够短以适合命令行参数缓冲区(最大长度取决于您的操作系统),shell 应该可以很好地处理这些问题。

Shell 如何将输入拆分为单独的命令和参数的规则相当复杂,您不应尝试模仿它们。相反,为用户找到一种简单的方法来单独指定参数(如命令行参数大小写),或者使用 shell 为您完成。如果您不进行任何拆分,您可能需要删除输入行末尾的换行符。

需要注意的一点是 forexecvp(file, args)args[0]应用程序看到的名称(如$0or argv[0]),并且args[1]是第一个参数。每个参数都由 NUL ( \0) 终止,就像字符串通常在 C 中一样,并且args指针数组必须以指针结尾NULL。如果没有参数,则args[1] == NULL.

于 2012-09-27T23:19:06.057 回答
0

为什么不直接使用系统命令...

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


int main ()
{
  int i;
  printf ("Executing command ls...\n");
  i=system ("ls");
  printf ("The value returned was: %d.\n",i);
  return 0;
}

更新:

#include  <stdio.h>
#include  <sys/types.h>
#include <stdlib.h>

void  main(void)
{
     pid_t  pid;

     pid = fork();
     if (pid == 0) // this is child process
     {
      int i;
      printf ("Executing command ls...\n");
      i=system ("ls");
      printf ("The value returned was: %d.\n",i);
     }
     else // this is paraent process 
     {
      int status=0
      wait(&status);
      printf ("Child process is returned with: %d.\n",status);
      }
}
于 2012-09-27T16:30:50.970 回答