c - waitpid() 总是返回 '-1'
问题描述
我有一个任务是在 C 中制作类似 unix 的 shell。用户可以输入“procs”,它打印所有正在运行的进程,在执行这个函数之前,我必须使用函数“updateProcessList”,它遍历进程列表并在帮助下waitpid() 更新进程的状态。如果一个进程“新”终止,我必须从列表中删除这个进程(仍然没有实现它)。我遇到的问题是更新功能。每次调用 waitpid() 都会返回 -1,错误号为“10”,这意味着父进程下不存在给定 id 的子进程,这当然不是真的(这个子进程处于僵尸状态),甚至是正在运行的进程像“sleep 5 &”('&' 表示它是非阻塞的,因此父进程不会' t 被阻止)未找到。手册页很难理解,并且在这个特定部分中对作业的解释非常糟糕(到目前为止,我已经在手册页的帮助下自己完成了所有工作,但是对于这个我迷路了,花了已经几个小时了,我被困住了)。如果有人能查明我在这里缺少的东西,我会非常高兴。谢谢!
#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;
}
解决方案
推荐阅读
- python-3.x - 我们如何将谷歌协作与 WordPress 结合起来?
- list - 向 Flutter_Map 添加标记数组仅在移动地图后显示
- php - 您可以在模型中使用在 MySQL 中创建的数据库视图吗?这是好的做法还是坏的做法?
- html - 带有位置固定按钮的溢出滚动框
- assembly - 修改 Makefile 生成汇编文件
- python - 如何删除 Pandas 数据框列中的 int?
- python - 为什么我在使用 matplotlib 直方图模块时得到不同的 len(bins) 和 numb_bins 值?
- google-cloud-firestore - Google Firestore get() 请求不存在的文档是否收费?
- visual-studio-code - 如何在 vscode 中更改 WSL(Windows 子系统 Linux)终端字体颜色?
- python - 在指定的索引范围内添加一个数字列表