我在C中实现了一个基本链表,作为开发简单shell的项目的一部分 - 它通过维护shell在后台运行的pid列表来支持进程的后台处理。代码如下。使用queue_process(some_pid)
插入第一次工作正常,但随后链表的行为就好像列表中从未有任何节点(即调试函数始终打印“无现有进程”)。我已经检查过这个文件以及调用这些函数的文件,以便将头指针重置为无效。我在链表逻辑中遗漏了什么吗?
对queue_process编辑的调用:发生在shell启动的子进程中,看起来像这样/编辑:queue_process(getpid())
谢谢!
void queue_process(pid_t pid_to_insert)
{
pmesg(2, "In queue_process.\n");
if (head == NULL)
{
pmesg(3, "No existing processes.\n");
head = malloc(sizeof(struct xssh_process));
head->pid = pid_to_insert;
head->next = NULL;
}
else
{
pmesg(3, "There are existing processes.\n");
struct xssh_process *new_process = malloc(sizeof(struct xssh_process));
new_process->next= head;
head = new_process;
}
print_processes();
}
void print_processes()
{
pmesg(2, "In print_processes.\n");
struct xssh_process *at_node = head;
if (head == NULL) { pmesg(2, "There are currently no background processes.\n"); return; }
pmesg(2, "Process IDs from head (most recently executed) to tail: %i -> ", at_node->pid);
while (at_node != NULL)
{
pmesg(2, "%i ->", at_node->pid);
at_node = at_node->next;
}
pmesg(3, "Head's pid in print is %i.\n", head->pid);
}
答案 0 :(得分:3)
这对你遇到的错误毫无帮助,但你的代码让我觉得过于复杂:
pmesg(2, "In queue_process.\n"); if (head == NULL) { pmesg(3, "No existing processes.\n"); head = malloc(sizeof(struct xssh_process)); head->pid = pid_to_insert; head->next = NULL; tail = malloc(sizeof(struct xssh_process)); tail = head; } else { pmesg(3, "There are existing processes.\n"); struct xssh_process *new_process = malloc(sizeof(struct xssh_process)); new_process->next= head; head = new_process; }
这可以简化很多。由于您无论如何都要插入列表的头部,因此对于空列表不需要单独的逻辑:
void queue_process(pid_t pid_to_insert) {
struct xssh_process *new_process = malloc(sizeof(*new_process));
new_process->pid = pid_to_insert;
new_process->next = head;
head = new_process;
}
同样,print_processes可以减少一点:
void print_processes() {
struct xssh_process *p;
for (p=head; p!=NULL; p=p->next)
printf("%d\n", p->pid);
}
OTOH,一个链表让我感觉不错 - 鉴于指针至少和PID一样大,至少有50%的内存是指针的开销。
答案 1 :(得分:1)
当变量的值神秘地改变时,通常是因为你写的超出了另一个变量的边界,恰好在内存中相邻。
尝试在head
上的调试器中设置一个观察点,只要该变量发生变化,它就会进入调试器。这可以让您快速跟踪问题。在gdb
中,命令为watch head
。
答案 2 :(得分:1)
根据您提供的额外信息:
对queue_process的调用发生在 子进程由shell启动 看起来像这样:
queue_process(getpid())
您正尝试添加到子进程中的链接列表(由fork()
创建),然后检查父级中的链接列表。
这不起作用 - fork()
创建一个完整的独立的副本。除了明确标记为共享的内存之外,在fork()
之后对变量进行的修改对每个进程都是私有的。父母不会看到孩子做出的修改,孩子也不会看到父母做出的修改。
您应该让父母致电queue_process(child_pid)
,其中child_pid
是fork()
的返回值。
答案 3 :(得分:0)
试试这个:
void queue_process(pid_t pid_to_insert)
{
pmesg(2, "In queue_process.\n");
if (head == NULL)
{
pmesg(3, "No existing processes.\n");
head = malloc(sizeof(struct xssh_process));
head->pid = pid_to_insert;
head->next = NULL;
// This malloc is not required
// tail = malloc(sizeof(struct xssh_process));
tail = head;
}
else
{
pmesg(3, "There are existing processes.\n");
struct xssh_process *new_process = malloc(sizeof(struct xssh_process));
new_process->next= head;
head = new_process;
}
print_processes();
}
void print_processes()
{
pmesg(2, "In print_processes.\n");
if (head == NULL) { pmesg(2, "There are currently no background processes.\n"); return; }
struct xssh_process *at_node = head;
// While at_node != null
do
{
pmesg(2, "%i ->", at_node->pid);
at_node = at_node->next;
}
while (at_node != null);
pmesg(3, "Head's pid in print is %i.\n", head->pid);
}