C:使用参数声明函数会改变其行为......?

时间:2012-10-24 01:21:05

标签: c parameters fork execve

我正在玩信号,分叉和execve,我写了一个玩具程序,使用fork()来创建一个调用另一个玩具程序的子进程。然后,父设置警报以在一定秒数后终止该功能。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <signal.h>

pid_t childPid;

pid_t Fork()
{
    pid_t pid;

    if ((pid = fork()) < 0)
        printf("Error:\n");
    return pid;
}

void killhandler(int sig)
/*This will be called when we receive a SIGALRM*/
{
    int status;
    printf("\nAssassin: *ksh* Received order to kill process: %d\n", (int)childPid);
    if (!(status = kill(childPid, SIGKILL))) {
        printf("Assassin: Clean and discreet. My work here is done. *ksh*\n");
    } else {
        printf("Assassin: He got away!\n");
    }
}

void forkyMcFork()
{
    pid_t pid;
    int status;
    /*Generate information for new program*/
    char* argv[] = {"problem5", "Hello"};
    char* envp[] = {"PANTS=JEANS"};
    char* func = "problem5";

    /* Create child process, child process calls executable "problem5" */
    if ((pid = Fork()) == 0) {
        printf("Child: I am a child! Woohoo!\n");
        if (execve(func, argv, envp) < 0)
            printf("Child: error, %s not found\n", func);
        while(1);
    }
    else {
        /* Parent process sets alarm, then prints a message depending on exit status*/
        childPid = pid;
        alarm(3);
        printf("Parent: I am the parent!\n");
        waitpid(-1, &status, 0);
        if (!WIFEXITED(status)) {
            printf("Parent: Oh no, what happened to my baby!!!\n");
            exit(0);
        } else {
            printf("Parent: Child came home without any problems.\n");
        }
    }
}

int main(int argc, char const *argv[])
{
    signal(SIGALRM, killhandler);
    forkyMcFork();
    return 0;
}

这是奇怪的部分:如果我将函数forkyMcFork()声明为不带参数,然后手动设置alarm()的参数,那么它就像我期望的那样工作:子进程启动{ {1}},要求用户提供一些输入,然后在3秒后problem5运行,找到子进程并将其杀死:

killhandler

但是,如果我声明$ ./forkfun Parent: I am the parent! Child: I am a child! Woohoo! Please type name. If finished press enter: Haha Please type name. If finished press enter: Assassin: *ksh* Received order to kill process: 42409 Assassin: Clean and discreet. My work here is done. *ksh* Parent: Oh no, what happened to my baby!!! $ 然后使用forkyMcFork(int secs),则找不到子程序中alarm(secs)语句应调用的外部程序。警报按预期运行,因此在几秒钟后,子进程被削减。

这是非工作代码:

execve()

这是输出:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <signal.h>

pid_t childPid;

pid_t Fork()
{
    pid_t pid;

    if ((pid = fork()) < 0)
        printf("Error:\n");
    return pid;
}

void killhandler(int sig)
/*This will be called when we receive a SIGALRM*/
{
    int status;
    printf("\nAssassin: *ksh* Received order to kill process: %d\n", (int)childPid);
    if (!(status = kill(childPid, SIGKILL))) {
        printf("Assassin: Clean and discreet. My work here is done. *ksh*\n");
    } else {
        printf("Assassin: He got away!\n");
    }
}

void forkyMcFork(int secs)
{
    pid_t pid;
    int status;
    /*Generate information for new program*/
    char* argv[] = {"problem5", "Hello"};
    char* envp[] = {"PANTS=JEANS"};
    char* func = "problem5";

    /* Create child process, child process calls executable "problem5" */
    if ((pid = Fork()) == 0) {
        printf("Child: I am a child! Woohoo!\n");
        if (execve(func, argv, envp) < 0)
            printf("Child: error, %s not found\n", func);
        while(1);
    }
    else {
        /* Parent process sets alarm, then prints a message depending on exit status*/
        childPid = pid;
        alarm(secs);
        printf("Parent: I am the parent!\n");
        waitpid(-1, &status, 0);
        if (!WIFEXITED(status)) {
            printf("Parent: Oh no, what happened to my baby!!!\n");
            exit(0);
        } else {
            printf("Parent: Child came home without any problems.\n");
        }
    }
}

int main(int argc, char const *argv[])
{
    signal(SIGALRM, killhandler);
    forkyMcFork(5);
    return 0;
}

所以要明确一点,这里唯一的代码区别是$ ./forkfun Parent: I am the parent! Child: I am a child! Woohoo! Child: error, problem5 not found Assassin: *ksh* Received order to kill process: 42400 Assassin: Clean and discreet. My work here is done. *ksh* Parent: Oh no, what happened to my baby!!! $ 是否被声明为forkyMcFork,在这种情况下它是有效的,还是采用void,在这种情况下它不会“T。发生了什么事?

1 个答案:

答案 0 :(得分:1)

Duck评论中有一个答案 - 所以只是总结一下:

  

int execve(const char * filename,char * const argv [],                     char * const envp []);

     

argv 是传递给新程序的参数字符串数组。 envp   是一个          字符串数组,通常为key = value形式,传递方式为          环境对新计划的影响。 argv和envp都必须以a终止          空指针。

因此我建议添加NULL以终止 envp