我在shell中处理后台进程时遇到了麻烦。我将pids存储在一个数组中,然后当我调用'jobs'时,它应该遍历数组,如果数字不是0,如果它仍然存活,它会打印,如果没有,它应该删除PID。我的结果非常不稳定。有人能看出我做错了吗?谢谢 结果:
ben$ sleep 5 &
Ben: started job 30290
ben$ jobs
30290
ben$ jobs
30290
ben$ jobs
30290
ben$ kill 30290
ben$ kill 30290: No such process
jobs
ben$ jobs
ben$ sleep 4s &
Ben: started job 30547
ben$ jobs
30547
ben$ kill 30547
ben$ jobs
30547
ben$ jobs
30547
ben$
第一个文件是main,第二个文件是我的函数文件
/*
Shell 1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdbool.h>
#define DELIMS " \t\r\n"
int main (int argc, char *argv[]) {
int ids[10];
initializeArray(ids);
while (1) {
char line[100];
char *temp;
char *split[15];
pid_t pid;
bool background=false;
printf("ben$ ");
//if cmd-d, exit shell
if(!fgets(line, sizeof(line), stdin)) {
printf("\n");
break;
}
line[strlen(line)-1]='\0';
temp=strtok(line," ");
if (strcmp(temp, "exit") == 0) {
break;
}
else if (strcmp(temp, "cd") == 0) {
char *arg = strtok(0, DELIMS);
if (!arg) {
fprintf(stderr, "cd missing argument.\n");
}
else {
chdir(arg);
}
}
else if (strcmp(temp, "jobs") == 0) {
printJobs(ids);
continue;
}
else {
int i=0;
while(temp != NULL) {
split[i]=temp;
temp=strtok(NULL," ");
i++;
}
split[i] = NULL;
if(strcmp(split[i-1], "&")==0) {
// printf("should do in background");
split[i-1]='\0';
background=true;
}
char *args[i];
int j;
for(j=0; j < i; j++){
args[j]=split[j];
}
pid=fork();
if(pid==0) {
if(background) {
fclose(stdin);
fopen("/dev/null","r");
}
execvp(args[0], args);
printf("This should not happen\n");
}
else {
if(!background) {
// printf("Not in background\n");
wait(&pid);
}
else {
printf("Ben: started job %d\n",pid);
insertPid(ids,pid);
background=false;
}
}
}
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void initializeArray(int ids[]);
void insertPid(int ids[],int pid);
void removePid(int ids[],int pid);
void printJobs(int ids[]);
void initializeArray(int ids[]) {
int i;
for(i=0;i<10;i++) {
ids[i]=0;
}
}
void insertPid(int ids[],int pid) {
// printf("inserting\n");
int i=0;
while(i<10) {
if(ids[i]==0) {
ids[i]=pid;
return;
}
i++;
}
printf("insert into list error");
return;
}
void removePid(int ids[],int index) {
// printf("removing %d\n",pid );
ids[index]=0;
return;
}
void printJobs(int ids[]) {
// printf("printing\n");
int i;
int pid;
for(i=0;i<10;i++) {
if(ids[i] != 0) {
// printf("job value %d",ids[i]);
pid=ids[i];
if(kill(pid,0) == 0) {
printf("%d\n",pid);
}
else{
removePid(ids,i);
}
}
}
}
答案 0 :(得分:0)
你怎么知道你的(背景)工作是否已经死亡?你在前台工作wait
- 所以你知道他们什么时候完成 - 但你不处理后台工作。无论你是杀了孩子还是他们最终自己过期(例如在例子中睡不着觉),你都不会知道。这也是您在输出列表中看到的内容。
解决这个问题的一种方法是为SIGCHLD设置信号处理程序,并在它们死亡时为它们设置waitpid
。然后更新您的作业数组。或者其中的一些变化。