jac*_*ter 1 c linux shell fork system-calls
我的第一个Stack Overflow帖子,我是网站上的潜伏者,但我真的想开始问我自己的一些问题!
我正在学习使用unistd.h库的fork()系统调用.我想测试一下我正在学习的内容.我已经在教科书中找到了关于在UNIX中创建简单进程的示例.我在OSX上这样做.我已经设置了一个创建shell的任务,我不想给出构建shell的完整答案,因此我为什么要问这个特定的系统调用,而不是整个程序.
代码本身运行完全正常,并提供预期的输出.
这是正常的代码:
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid;
pid = fork();
if(pid == 0){
printf("\nI'm the child\n\n");
}
else if(pid > 0){
printf("\nI'm the parent, child has pid: [%d]\n", pid);
}
else{
printf("ERROR");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,当我把它放在我的shell程序中时,它引起了我在网上找到的一个叉炸弹.
使用命令'test'调用创建此过程的函数.当我运行该函数时,它提供与独立版本相同的输出,但是当我继续前进并退出时,似乎在无限循环中再次调用该测试函数.然后,我无法杀死进程因为我的计算机滞后,显然是因为正在创建一堆进程而我必须重新启动计算机.我现在已经完成了几次,因为每次运行都需要执行重启,因此无法进行测试.
我有一个期望退出命令结束的while循环.代码应该是自解释的,如下所示.我知道很多这是不好的做法,我只是试图测试这些概念,从研究我相信我应该使用wait()系统调用,但我想了解为什么我的代码导致这种情况发生.
完整的计划:
main.c中
#include "shell.h"
int main() {
clear();
printf("Jack's Shell\n");
shellLoop();
clear();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
shell.c
#include "shell.h"
void shellLoop(){
char command[MAX_STRING_LEN];
int exit = 1;
while (exit != 0){
printf("\njackdewinter$ ");
scanf("%s", &command);
exit = commandInterpreter(command);
}
}
int commandInterpreter(char * cmd){
char message[MAX_STRING_LEN];
if(strcmp(cmd, "exit") == 0){ /* Best way to test strings (Not just characters.) */
return 0;
}
else if(strcmp(cmd, "info") == 0){
info();
return 1;
}
else if(strcmp(cmd, "pwd") == 0){
shellMessage("Call PWD");
return 1;
}
else if(strcmp(cmd, "cd") == 0){
shellMessage("Call CD");
return 1;
}
else if(strcmp(cmd, "test") == 0){
shellMessage("Test Called.");
test();
return 1;
}
else if(strcmp(cmd, "help") == 0){
shellMessage("Call HELP");
return 1;
}
else{
shellMessage("Incorrect command entered.\nType help for assistance and a list of commands.");
return 1;
}
}
void info(){
shellMessage("This shell was created by Jack Dewinter");
}
void test(){
pid_t pid;
pid = fork();
if(pid == 0){
printf("Child\n");
}
else if(pid > 0){
printf("I'm the parent, child has pid %d\n", pid);
}
else{
printf("ERROR");
}
}
void shellMessage(char * message){ /* Using this for consistent shell messages. */
printf("\n%s\n", message);
}
Run Code Online (Sandbox Code Playgroud)
shell.h
#define MAX_STRING_LEN 80
#define clear() printf("\033[H\033[J") /* Terminal escape codes for clearing the console */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
void shellLoop();
int commandInterpreter(char * cmd);
void info();
void test();
void shellMessage(char * message);
Run Code Online (Sandbox Code Playgroud)
任何帮助将不胜感激,谢谢!
使用时创建新进程fork,子进程从fork的位置继续.所以你的孩子打印"孩子",然后它从中返回test.所以它继续运行只有父运行的代码才能运行.
您不会在较小的代码段中看到这一点,因为您会立即返回,main导致子进程退出.
完成它后,你需要让孩子退出.此外,父母应该wait为孩子,这样你就不会留下僵尸进程.
void test(){
pid_t pid;
pid = fork();
if(pid == 0){
printf("Child\n");
_exit(0); // exit child; use _exit instead of exit
//to prevent atexit handlers from being called
}
else if(pid > 0){
printf("I'm the parent, child has pid %d\n", pid);
// wait for child to finish
wait(NULL);
}
else{
printf("ERROR");
}
}
Run Code Online (Sandbox Code Playgroud)
此外,在您屏蔽库函数时shellLoop,将变量重命名exit为其他内容exit.