问题描述
我接到了一个用 C 语言制作类 Unix 外壳的任务。 用户可以输入打印所有正在运行的进程的“procs”,在执行此函数之前,我必须使用函数“updateProcessList”,它遍历进程列表并在 waitpid() 的帮助下更新进程的状态。如果一个进程“刚刚”终止,我必须从列表中删除这个进程(仍然没有实现它)。 我遇到的问题是更新功能。对 waitpid() 的每次调用都返回 -1,错误号为“10”,这意味着在父进程下不存在给定 id 的子进程,这当然不是真的(这个子进程处于僵尸状态),甚至是正在运行的进程像“sleep 5 &”(“&”表示它是非阻塞的,因此父进程不会被阻塞)没有找到。 手册页很难理解,这个特定部分对作业的解释也很蹩脚(直到现在我已经在手册页的帮助下自己完成了所有工作,但是对于这个我迷失了,花了已经几个小时了,我被卡住了)。 如果有人能指出我在这里遗漏了什么,我会很高兴。 谢谢!
#include "LineParser.h"
#include <linux/limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#define TERMINATED -1
#define RUNNING 1
#define SUSPENDED 0
#define SIZE 2048
#define FORKED(x) (strcmp(x,"cd") != 0 && strcmp(x,"procs") != 0)
int debugMode = 0;
typedef struct process{
cmdLine* cmd; /* the parsed command line*/
pid_t pid; /* the process id that is running the command*/
int status; /* status of the process: RUNNING/SUSPENDED/TERMINATED */
struct process *next; /* next process in chain */
} process;
process **processList;
void updateProcessstatus(process* process_list,int pid,int status) {
process* temp = process_list;
while (temp != NULL) {
if (temp -> pid == pid) {
temp -> status = pid;
return;
}
temp = temp -> next;
}
}
void updateProcessList(process **process_list) {
int status;
process **curr = process_list;
while ((*curr) != NULL) {
pid_t statusChangedId = waitpid((*curr) -> pid,&status,WNOHANG | WUNTRACED | WCONTINUED);
if (statusChangedId == -1) {
perror("");
printf("%d\n",errno);
printf("%d\n",(*curr) -> pid);
}
if (statusChangedId > 0) {
updateProcessstatus(*curr,statusChangedId,status);
}
curr = &((*curr) -> next);
}
}
void addProcess(process** process_list,cmdLine* cmd,pid_t pid) {
process **tail = process_list;
while (*tail != NULL) {
tail = &((*tail) -> next);
}
*tail = (process *) malloc(sizeof(process));
(*tail) -> cmd = cmd;
(*tail) -> pid = pid;
(*tail) -> status = RUNNING;
(*tail) -> next = NULL;
}
void printProcessList(process** process_list) {
updateProcessList(process_list);
process *curr = *process_list;
while (curr != NULL) {
printf("%-13s%-13s%s\n","PID","Command","STATUS");
printf("%-13d%-13s%s\n",curr -> pid,curr -> cmd -> arguments[0],(curr -> status) == -1 ? "TERMINATED" :
(curr -> status) == 0 ? "SUSPENDED" :
"RUNNING");
curr = curr -> next;
}
}
void execute(cmdLine *pCmdLine) {
if (!FORKED(pCmdLine -> arguments[0])) {
if (strcmp(pCmdLine -> arguments[0],"cd") == 0) {
if (chdir(pCmdLine -> arguments[1]) < 0) {
perror("");
fprintf(stderr,"%d\n",errno);
}
}
else if (strcmp(pCmdLine -> arguments[0],"procs") == 0) {
printProcessList(processList);
}
free(pCmdLine);
}
else {
// if we're here,it means user input wasn't "cd" nor "procs"
pid_t id = fork();
if (id == -1) {
fprintf(stderr,"fork() Couldn't open child,terminating...");
_exit(-1);
}
if (id != 0) { // this is the parent and it will be blocked if needed
addProcess(processList,pCmdLine,id);
if (pCmdLine -> blocking) {
waitpid(id,NULL,0);
}
}
else {
execvp(pCmdLine -> arguments[0],pCmdLine -> arguments);
perror("Error "); // returns here only if execv encounterd some error
_exit(errno);
}
}
//_exit(0);
if (debugMode) {
fprintf(stderr,"Process ID: %d\nExecuting command: %s\n",getpid(),pCmdLine -> arguments[0]);
}
// if (!FORKED(pCmdLine -> arguments[0]))
// freeCmdLines(pCmdLine);
}
int main(int argc,char **argv) {
processList = (process **) malloc(4);
char cmdBuffer[SIZE];
char cwdName[PATH_MAX];
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i],"-d") == 0) {
debugMode = 1;
}
}
getcwd(cwdName,PATH_MAX);
printf("%s\n",cwdName);
while (fgets(cmdBuffer,SIZE,stdin) != NULL) {
if (strncmp(cmdBuffer,"quit",4) == 0) {
break;
}
cmdLine* currCmd = parseCmdLines(cmdBuffer);
execute(currCmd);
}
freeProcessList(*processList);
return 0;
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)