【问题标题】:C, Fork(), take CL argument and execute CHDIRC, Fork(), 取 CL 参数并执行 CHDIR
【发布时间】:2018-11-05 23:10:25
【问题描述】:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
char *getcwd(char *buf, size_t size); //define getcwd
char PATH_MAX[1024]; //define max size of path


int chdir(const char *path);


int main(int argc, char *argv[]) { // gets arguments when program ran, no arguments means argv=1

    pid_t pid; //process ID = pid
    pid=fork();
    char cwd[1024]; //compare directory to max character size

   if(pid==0){ //child has been forked! //child process created
    int ret;
    printf("Child PID=%d\n", getpid());
    getcwd(PATH_MAX, sizeof(PATH_MAX));
    printf(" My current working directory is: %s\n", PATH_MAX);

    ret= execl("/bin/ls", "ls", "-a", "-l", "-h", NULL);
    printf("%d\n", ret); //why isn't this printed out?
   }

    //} 
   else {
    int status;
        //parent process
        //wait for child to complete
        printf("Parent PID=%d\n", getpid());
        if (waitpid(pid, &status, 0) == -1) {
            printf("ERROR");
        }
        else {
        printf("Child done.\n");
        getcwd(PATH_MAX, sizeof(PATH_MAX));

        printf("0");
        exit(0);
    }
}
}

我留下了注释掉的代码,这样你就可以看到我的思考过程。如果我的理解是正确的,shell(终端)是它自己的进程,所以当你调用 fork 时,它会创建一个新的子进程,并且它的父进程成为 shell。因此,在子进程中尝试 chdir 不会转换到 shell 并且您将保留在同一目录中,因此您需要在父 PID(现在是 shell)中执行 chdir 函数,是吗?

我很难弄清楚我应该把这个 chdir() 命令放在哪里,以及我需要使用什么类型的 exec 来执行终端命令。

在终端中运行时,我正在测试 3 个不同的命令作为命令行参数。这是在使用gcc -o script script.c 制作文件之后

$ ./script 
 result - print out current directory
 print out "Usage: "<dir>" string. no command executed

$ ./script . 

result -"Executing ls . --all -l --human-readable" string

  executes above commands 

$./script / 

result - should execute above commands but change directory before 

executing

$./script /blah/blah

result - can't execute chdir

exit status: 1

我相信这段代码应该会导致子进程返回一个 -1 来终止它,或者如果我的 if 语句是正确的,它会打印出错误消息。

任何帮助将不胜感激,我相信我理解了逻辑,或者至少在某种程度上。只是很难实现chdir

【问题讨论】:

  • 请注意,您没有“定义”getcwd()——您只需声明它。不过,您不需要声明它; &lt;unistd.h&gt; 标头应该为您声明它。与chdir() 类似。您可能需要指定 #define _XOPEN_SOURCE 700 或类似的东西才能使声明可见 - 这取决于您的编译器选项和您正在使用的平台。
  • 所有这些注释使代码难以阅读。请阅读有关如何创建 MCVE (minimal reproducible example) 的信息。任何与您的问题无关的内容都应省略。代码中大约一半的行是 cmets;那是很多cmets!
  • 您的符号char PATH_MAX[1024]; //define max size of path 很奇怪。通常,PATH_MAX 由系统为您定义——如果未定义,您可能应该使用_POSIX_PATH_MAX 代替。无论哪种方式,PATH_MAX 都是一个数字(用于指定保存路径名的数组的大小),而不是字符数组。请参阅 POSIX &lt;limits.h&gt;
  • 谢谢乔纳森。我将编辑上面的代码并删除 cmets。我最初把它们放在那里,这样每个人都可以看到我做了什么尝试,以及我是否走在正确的轨道上。
  • exec()-family 函数仅在 exec 进程失败时返回。如果调用成功,则旧程序不再运行(已替换为执行过的程序)-这就是为什么您的 why not this is print out? 不打印的原因出来。

标签: c terminal


【解决方案1】:

我稍微煮了一下你的程序,得到了以下结果:

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

int main(int argc, char *argv[])   // gets arguments when program ran, no arguments means argv=1
{
    int ret;
    pid_t pid; //process ID = pid
    pid=fork();
    char cwd[1024]; //compare directory to max character size
    char newPath[200]=".";
    if( argc > 1 )
    {
        strcpy(newPath,argv[1]);
    }
    ret=chdir(newPath);
    if( ret < 0 )
    {
        printf("Problem switching to :%s\n", newPath);
        perror("chdir");
        exit(ret);
    }
    if(pid==0){ //child has been forked! //child process created
        int ret;
        printf("Child PID=%d\n", getpid());
        getcwd(cwd, sizeof(cwd));
        printf(" My current working directory is: %s\n", cwd);

        ret= execl("/bin/ls", "ls", "-a", "-l", "-h",  NULL);
        printf("%d\n", ret); //why isn't this printed out?
    }
    else {
        int status;
        //parent process
        //wait for child to complete
        printf("Parent PID=%d\n", getpid());
        if (waitpid(pid, &status, 0) == -1) {
            printf("ERROR");
        } else
        {
            printf("Child done. stat=%d\n", status);
            getcwd(cwd, sizeof(cwd));
            printf("Parent cwd:%s\n", cwd);

            printf("0");
            exit(0);
        }
    }
}

您的理解并不完全正确。当您从终端上的命令行执行程序时,shell 会分叉并执行您正在运行的进程。通常,父 shell 进程一直等到子进程完成。您创建了一个子进程并执行了另一个 exec 和另一个等待。父 shell 耐心等待你完成,fork 进程等等。

让我们看看:

  1. 我将chdir 放在您的主程序中,以显示孩子跟随父母。
  2. 子进程不会更改父进程的工作目录。 Unix 和 Linux 不是这样工作的。
  3. 当您运行execl 时,就是这样。除非它不能执行,否则没有回报。 exec* 的重点是你正在用一个新的可执行文件吹走你当前正在运行的程序。没有什么可返回的。
  4. 如果要查看child的返回码,查看wait返回的状态。在这种情况下,ls 运行良好,因此返回码为零。如果您添加了“baddir”的最后一个参数(不存在),您将看到 ls 非零返回码,在本例中为 512。

【讨论】:

    猜你喜欢
    • 2014-11-29
    • 1970-01-01
    • 2019-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 2011-06-27
    • 1970-01-01
    相关资源
    最近更新 更多