我正在玩弄信號,叉子和execve,我寫了一個玩具程序,它使用fork()
來創建一個調用另一個玩具程序的子進程。然後,父母設置一個警報,在一定的秒數後終止該功能。C:使用參數聲明函數會改變其行爲...?
#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()
,然後它就像我希望:子進程開始problem5
,其請求一些來自用戶的輸入,然後3秒,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)
,應當由被稱爲外部程序找不到子項目中的語句。警報按預期運行,因此在幾秒鐘後,子進程將被削減。
這裏的非工作代碼:
#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
,在這種情況下它可以工作,或者採取int secs
,在這種情況下它不會。這是怎麼回事?
當你從'execve'得到錯誤時,打印'errno'的值,或者更好的使用['strerror'](http://linux.die.net/man/3/strerror)來獲得錯誤代碼的可打印文本。 –
也請顯示_fails_程序,而不是成功的程序。 –
在ForkyMcFork()的argv和envp變量的末尾添加一個空參數。你可能只是幸運的版本作品。 – Duck