Предотвращение процессов зомби в самореализованной оболочке Linux (C ++)

Я сам внедряю оболочку Linux. Я почти закончил, но мне нужно разобраться с проблемой зомби-процессов. В этой программе добавив&»для команды вы можете указать, что команда должна выполняться в фоновом режиме.

Например, спать 30 & будет выполнять функцию ожидания в течение 30 секунд, но сразу же позволит пользователю ввести другую команду без ожидания.

Моя проблема в том, что в моей текущей реализации запускается фоновый процесс, но я не знаю, как заставить его сообщить программе, когда она закончила выполнение.

Мне нужно знать, когда он закончил выполнение, потому что у меня есть встроенная функция, называемая «задания». Эта функция распечатает список программ, запущенных в данный момент.

В идеале, если я выполню «сон 30″ &»и затем сразу же запустите» задания «до того, как сон закончится, он должен показать примерно так:

[1] [ПРОЦЕСС ID ЗДЕСЬ] сон 30 &

Однако, если прошло 30 секунд, и режим сна завершился, я хочу показать, что ни один из процессов не запущен. Прямо сейчас, если я бегу «спать 30 &», это проявляется как процесс зомби (в команде ps -e). Я не хочу этого. Как мне это исправить?

Вот мой код:

#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <stack>
#include <vector>
#include <ctype.h>
#include <sstream>
using namespace std;

#define MAX_INPUT_STRING_SIZE 80

//This function executes the command that was entered
int executeCommand(char ** commandArguments, int mode, char **supplementalPointer);

//This function parses the command that was entered
int parseCommand(char* inputString, char * commandArguments[], char** supplementalPointer,
int *modePointer);

//A bit of string handling
void chop(char * sourcePointer);

//print the history of commands
void printHistory();

//print the list of background processes running
void printJobs();

//Return the nth command in the history of commands
string returnNth(int nth);//Modes
#define NORMAL 00
#define OUTPUT_REDIRECT 11
#define INPUT_REDIRECT 22
#define PIPELINE 33
#define BACKGROUND 44

//This struct defines a job that is stored in the list of background processes
struct job
{
pid_t processID;
string command;
job(pid_t pid, string com)
{
processID = pid;
command = com;
}
};//The history of commands entered
stack<string> commandHistory;

//A place to store commands that have been popped before that are added back in
stack<string> popHistory;

//The list of background processes currently running
vector<struct job> jobList;

int main(int argc, char *argv[])
{
int i, mode = NORMAL, numOfArguments;
size_t length = MAX_INPUT_STRING_SIZE;
char *cpt, *inputString, *commandArguments[MAX_INPUT_STRING_SIZE], *supplement = NULL;

//The string that holds the command that the user entered
inputString = (char*)malloc(sizeof(char)*MAX_INPUT_STRING_SIZE);

char currentDirectory[100];

//continue until "quit" has been entered
while(strcmp(inputString, "quit\n") != 0)
{
mode = NORMAL;

//get and print the current working directory
getcwd(currentDirectory, 100);
cout<<"%"<<currentDirectory<<"% ";

//get the command from the user
getline(&inputString, &length, stdin);
executeFromHistory:
string inputStringS(inputString);

//push the command to the history stack
commandHistory.push(inputStringS);

//quit the program
if(inputStringS == "quit\n")
{
continue;
}

//print the history
else if(inputStringS == "history\n")
{
printHistory();
continue;
}

//print the list of jobs
else if(inputStringS == "jobs\n")
{
printJobs();
continue;
}

else if(inputStringS[0] == '!')
{
commandHistory.pop();

//execute the most recent command
if(inputStringS[1] == '!')
{
if(commandHistory.empty())
{
cout<<"No commands in history"<<endl;
}
else
{
inputStringS = commandHistory.top();
strcpy(inputString, inputStringS.c_str());
goto executeFromHistory;
}
}

//Execute the nth command in history (specified by user)
else if(isdigit(inputString[1]))
{
int nth;
inputStringS = inputStringS.substr(1);
istringstream iss(inputStringS);
iss >> nth;
if(commandHistory.size() < nth || nth < 1)
{
cout<<"No such command could be found"<<endl;
}
else
{
inputStringS = returnNth(nth);
strcpy(inputString, inputStringS.c_str());
goto executeFromHistory;
}
}
else
{
continue;
}
}
//Parse a command and execute
else
{
numOfArguments = parseCommand(inputString, commandArguments, &supplement, &mode);

//Change directory
if(strcmp(*commandArguments, "cd") == 0)
{
chdir(commandArguments[1]);
}
else

//Execute
{
int returnstatus = executeCommand(commandArguments, mode, &supplement);
if(returnstatus == -1)
{
cout<<"Execution failed"<<endl;
continue;
}
}
;
}
}
return 0;
}

int parseCommand(char * inputString, char *commandArguments[], char **supplementalPointer,
int *modePointer)
{
int numOfArguments = 0;
bool terminate = false;
char* sourcePointer = inputString;

//Continue until the character we are on is NULL and terminate flag has been tripped
while(*sourcePointer !=  '\0' && !terminate)
{

//New argument
*commandArguments = sourcePointer;
numOfArguments++;
while(*sourcePointer != ' ' && *sourcePointer != '\t' && *sourcePointer != '\0'
&& *sourcePointer != '\n' && !terminate)
{

//Handle various special characters
switch(*sourcePointer)
{
case '&':
*modePointer = BACKGROUND;
*commandArguments = '\0';
*sourcePointer++;
while(*sourcePointer == ' ' || *sourcePointer == '\t')
{
sourcePointer++;
}
break;
case '>':
*modePointer = OUTPUT_REDIRECT;
*commandArguments = '\0';
*sourcePointer++;
while(*sourcePointer == ' ' || *sourcePointer == '\t')
{
sourcePointer++;
}
*supplementalPointer = sourcePointer;
chop(*supplementalPointer);
terminate = true;
break;
case '<':
*modePointer = INPUT_REDIRECT;
*commandArguments = '\0';
sourcePointer++;
while(*sourcePointer == ' ' || *sourcePointer == '\t')
{
sourcePointer++;
}
*supplementalPointer = sourcePointer;
chop(*supplementalPointer);
terminate = true;
break;
case '|':
*modePointer = PIPELINE;
*commandArguments = '\0';
sourcePointer++;
while(*sourcePointer == ' ' || *sourcePointer == '\t')
{
sourcePointer++;
}
*supplementalPointer = sourcePointer;
terminate = true;
break;
}
sourcePointer++;
}
while((*sourcePointer == ' ' || *sourcePointer == '\t' || *sourcePointer == '\n') &&
!terminate)
{
*sourcePointer = '\0';
sourcePointer++;
}
commandArguments++;
}
*commandArguments = '\0';
return numOfArguments;
}

void chop(char * sourcePointer)
{
while(*sourcePointer != ' ' && *sourcePointer != '\t' && *sourcePointer != '\n')
{
sourcePointer++;
}
*sourcePointer = '\0';
}

int executeCommand(char** commandArguments, int mode, char ** supplementalPointer)
{
pid_t pid1;
pid_t pid2;
FILE *filePointer;
int mode2 = NORMAL;
int numOfArguments;
int status1;
int status2;
char * commandArguments2[MAX_INPUT_STRING_SIZE];
char * supplement2 = NULL;
int pipes[2];

//Pipeline
if(mode == PIPELINE)
{
if(pipe(pipes))
{
cout<<"Pipe failed"<<endl;
return -1;
}
parseCommand(*supplementalPointer, commandArguments2, &supplement2, &mode2);
}
pid1 = fork();
string str(*commandArguments);

//Push the command to the list of running processes
jobList.push_back(job(pid1, str));
if(pid1<0)
{
cout<<"Fork failed"<<endl;
return -1;
}

//Child process
else if(pid1 == 0)
{
switch(mode)
{
case BACKGROUND:
//Child process is a background process
setpgid(0, 0);
case OUTPUT_REDIRECT:
filePointer = fopen(*supplementalPointer, "w+");
dup2(fileno(filePointer), 1);
break;
case INPUT_REDIRECT:
filePointer= fopen(*supplementalPointer, "r");
dup2(fileno(filePointer), 0);
break;
case PIPELINE:
close(pipes[0]);
dup2(pipes[1], fileno(stdout));
close(pipes[1]);
break;
}
execvp(*commandArguments, commandArguments);
}

//Parent process
else
{
if(mode == BACKGROUND)
{

//Wait for child process to complete
;
}
else if(mode == PIPELINE)
{
waitpid(pid1, &status1, 0);
pid2 = fork();
string str2(*commandArguments2);
jobList.push_back(job(pid2, str2));
if(pid2 < 0)
{
cout<<"fork failed"<<endl;
return -1;
}
else if(pid2 == 0)
{
close(pipes[1]);
dup2(pipes[0], fileno(stdin));
close(pipes[0]);
execvp(*commandArguments2, commandArguments);
}
else
{
close(pipes[0]);
close(pipes[1]);
}
}
else
{
waitpid(pid1, &status1, 0);

}
}
return 1;
}

void printHistory()
{
int commandHistorySize = commandHistory.size();
int i;
string commandPop;
for(i = commandHistorySize; i > 0; i--)
{
commandPop = commandHistory.top();
cout<<i<<" "<<commandPop;
commandHistory.pop();
popHistory.push(commandPop);
}
for(i = 0; i < commandHistorySize; i++)
{
commandPop = popHistory.top();
popHistory.pop();
commandHistory.push(commandPop);
}
}

//Print list of running processes
void printJobs()
{
int i;
for(i = 0; i < jobList.size(); i++)
{

//If the process is no longer running, remove it from the list
if(kill(jobList[i].processID, 0 )!= 0)
{
jobList.erase(jobList.begin() + i);
}
}
for(i = 0; i < jobList.size(); i++)
{
cout<<"["<<i+1<<"] "<<jobList[i].processID<<" "<<jobList[i].command<<endl;
}
}

string returnNth(int nth)
{
int i;
int commandHistorySize = commandHistory.size();
string commandPop;
for(i = commandHistorySize; i > nth; i--)
{
commandPop = commandHistory.top();
commandHistory.pop();
popHistory.push(commandPop);
}
string returnvalue = commandHistory.top();
for(i = commandHistorySize; i > nth; i--)
{
commandPop = popHistory.top();
popHistory.pop();
commandHistory.push(commandPop);
}
return returnvalue;
}

0

Решение

Вам необходимо создать обработчик для SIGCHLD, который ожидает процесс, а затем включает обработчик, используя сигнал (SIGCHLD, обработчик).

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]