我正在编写一个程序,该程序可以从文件中读取linux
命令,并使用fork()
和execvp()
并行运行它们,并且运行良好。
while((current = GetNextCommand(current)) != NULL){
char currentCommand[WIDTH - 1];
current->active = true;
strcpy(currentCommand, current->command);
int j=0;
int ctr=0;
char newString[LENGTH][WIDTH];
for(int i = 0; i <= strlen(currentCommand); i++){
// if space or NULL found, assign NULL into newString[ctr]
if(currentCommand[i]==' '|| currentCommand[i]=='\0')
{
newString[ctr][j]='\0';
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr][j] = currentCommand[i];
j++;
}
}
char *exe[ctr + 1];
for(int i = 0; i < ctr; i++){
exe[i] = strdup(newString[i]);
}
exe[ctr] = NULL;
t = clock();
clock_gettime(CLOCK_MONOTONIC, &start);
current->starttime = start.tv_sec;
current->PID = (pid = fork());
if(pid < 0){
fprintf(stderr, "fork Failed\n"); //output in stderr if fork fails and return
exit(1);
}
else if(pid == 0){
execvp(exe[0], exe);
//fails
exit(2);
}
}
我的文件是
sleep 3
ls -latr
sleep 1
pwd
sleep 1
wc /etc/passwd
sleep 10
在父进程中,如果命令的运行时间大于2秒,我需要获取每个子进程的运行时间并重新运行该命令。如果命令的运行时间大于2,我将继续运行该命令,直到用户使用kill -sig pid
或pkill sleep
终止该进程为止。我使用for循环并设置了相应的wait(&status)数。在我的文件中,sleep 3
和sleep 10
将大于2秒。 sleep 3
的进程完成工作后,它将返回到父级,并且sleep 10
仍在运行。现在使用pkill sleep
会很好,因为sleep 10
将继续在父进程中运行。但是,当它们都从子进程中退出并且我使用kill -sig pid
时,整个程序都退出了。因此,在这种情况下如何同时运行它们(sleep 3
和sleep 10
)?
for(int i = 0; i < nodeIndex - 1; i++){
int status;
int pid = wait(&status);
clock_gettime(CLOCK_MONOTONIC, &finish);
CommandNode* cNode;
cNode = FindCommand(head->nextCommandPtr, pid);
elapsed = finish.tv_sec - cNode->starttime;
printf("%ld\n", elapsed);
if(elapsed < 2){
cNode->active = false;
}
else{
char rerunCommand[WIDTH - 1];
strcpy(rerunCommand, cNode->command);
int j=0;
int ctr=0;
char newString[LENGTH][WIDTH];
for(int i = 0; i <= strlen(rerunCommand); i++){
// if space or NULL found, assign NULL into newString[ctr]
if(rerunCommand[i]==' '|| rerunCommand[i]=='\0')
{
newString[ctr][j]='\0';
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr][j] = rerunCommand[i];
j++;
}
}
char *exe[ctr + 1];
for(int i = 0; i < ctr; i++){
exe[i] = strdup(newString[i]);
}
exe[ctr] = NULL;
while(elapsed > 2){
int pid2;
t = clock();
clock_gettime(CLOCK_MONOTONIC, &start);
cNode->starttime = start.tv_sec;
cNode->PID = (pid2 = fork());
if(pid2 < 0){
fprintf(stderr, "fork Failed"); //output in stderr if fork fails and return
exit(1);
}
else if(pid2 == 0){
printf("What happened here.\n");
execvp(exe[0], exe);
exit(2);
}
else{
wait(&status);
clock_gettime(CLOCK_MONOTONIC, &finish);
elapsed = finish.tv_sec - cNode->starttime;
if(elapsed > 2) {
printf("What is this: %d %d\n", pid2, cNode->PID);
}
}
}
}
}
关于标题中的问题:
是的,可以循环直到返回值是-1
是的,的确,这是确保所有孩子在继续之前都已经完成的正确方法:
pid_t pid;
...
while((pid = wait(NULL)) >= 0)
printf("child pid=%d ended.\n", pid); /* or whatever you want */
/* no more children active after this point, you don't need
* to check the value of errno, except if you allow this
* process to be interrupted by a signal. */