Commit e54c009a authored by Dong Hung Pham's avatar Dong Hung Pham 🤡
Browse files

Add new file

parent 76db2ea7
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <unistd.h>
#include<sys/wait.h>
#define LSH_TOK_BUFSIZE 64
#include <signal.h>
#define TOK_DELIM " \t\r\n\a"
bool cont = true;
bool fg = false;
// hier sind mit input zu arbeiten
char *read_line(void)
{
char *line = NULL;
size_t bufsize = 0; // have getline allocate a buffer for us
if (getline(&line, &bufsize, stdin) == -1){
if (feof(stdin)) {
exit(EXIT_SUCCESS); // We recieved an EOF
} else {
perror("readline");
exit(EXIT_FAILURE);
}
}
return line;
}
char **split_line(char *line)
{
int bufsize = LSH_TOK_BUFSIZE, position = 0;
char** tokens = (char**)malloc(bufsize * sizeof(char*));
char *token;
if (!tokens) {
fprintf(stderr, "lsh: allocation error\n");
exit(EXIT_FAILURE);
}
token = strtok(line, TOK_DELIM);
while (token != NULL) {
tokens[position] = token;
position++;
if (position >= bufsize) {
bufsize += LSH_TOK_BUFSIZE;
tokens = (char**)realloc(tokens, bufsize * sizeof(char*));
if (!tokens) {
fprintf(stderr, "lsh: allocation error\n");
exit(EXIT_FAILURE);
}
}
token = strtok(NULL, TOK_DELIM);
}
tokens[position] = NULL;
return tokens;
}
void initshell(void){
const char* CLEAR_SCREEN_ANSI = " \e[1;1H\e[2J"; //These two lines clear the console
write(STDOUT_FILENO, CLEAR_SCREEN_ANSI,12); //These two lines clear the console
}
void printshell(void){
printf("myshell<"); //display prompt
}
// end of input output function
//struct to control process , with job i set pgid to avoid complex things(exp:chromium has a lots of pid
//so we only work with the 1st pid , which i set in loop function )
struct process {
pid_t mPid;
bool completed;
} ;
// declare variable
bool background;
pid_t pid, wpid;
int status ;
std::vector<process> mVector;
void handle_SIGTSTP(int signum) {
cont = false; // to avoid sigchld change state of completed in process
fg = true;
if (background == true){ // we only stop foreground process ...
printf ("PID is%d\n",pid);
kill(pid,SIGSTOP);// sigstop
}
}
// fg function
void fContinue(pid_t p){
fg = true; // to avoid sigchld change state of completed in process
cont = false;// we changed its state here in (1)
if (kill(p,SIGCONT) < 0)
perror ("kill (SIGCONT)");
wpid = waitpid(p, &status, WUNTRACED);
// (1)
for (int i = 0; i < mVector.size();i++ ){
if (mVector[i].mPid == p ){
mVector[i].completed = true;
}
}
}
// bg function
void bContinue(pid_t p){
cont = false; // to avoid sigchld change state of completed in process
if (kill(p,SIGCONT) < 0)
perror ("kill (SIGCONT)");
}
bool printZombie(std::vector<process> v){
int count = 0;
for (int i = 0; i < v.size();i++ ){
if (v[i].completed == false){
printf("These processes are still running %d \n",v[i].mPid);
count++;
}
}
printf("there are number pids/processes: %d \n",v.size());
if (count == 0) return true;
else return false;
}
void handle_SIGCHLD(int signum)
{
pid_t t2 = pid;
int count = 0; //to change state of foreground process
if(cont ){
pid_t t ;
if (!fg){
if((t = waitpid(-1, &status, WNOHANG)) != -1){ // its gonna wait until a background process terminated
count++;
for (int i = 0; i < mVector.size();i++ ){
if (mVector[i].mPid == t ){ //t is the pid of the process, which did call this singal
mVector[i].completed = true;
printf("caugt a sigchld\n");
}
}
}
}
if (count == 0) {//to change state of foreground process
for (int i = 0; i < mVector.size();i++ ){
if (mVector[i].mPid == t2 ){
printf("caugt a sigchld\n");
mVector[i].completed = true;
}
}
}
}
fg =false; // set back the condition bool variable
cont = true;
}
void loop(void){
char *line;
char **args;
signal(SIGTSTP,handle_SIGTSTP);
signal(SIGCHLD,handle_SIGCHLD);
while(1){
// setup
printshell();
line = read_line();
int size = strlen(line);
background = true;
if (line[size-2]=='&'){
background = false;
line[size-2] = '\0';
}
args = split_line(line);
// real work
if (strcmp(line, "logout") == 0) {
if (printZombie(mVector)){
printf("press y to quit\n");
char c = getchar();
if ('y' == c){
break;
}
continue;
}
}
else if(strcmp(args[0] , "fg") == 0){
printf("FG is %d : \n",atoi(args[1]));
fContinue(atoi(args[1]));
}
else if(strcmp(args[0] , "bg") == 0){
printf("BG is %d : \n",atoi(args[1]));
bContinue(atoi(args[1]));
}
// new process
else{
pid = fork();
struct process newP;
if (pid == 0) {
setpgid(0,getpid());
// Child process
if (execvp(args[0], args) == -1) {// excute command
perror("something bad happen");
}
exit(EXIT_FAILURE);
setpgid(0,getpid());
}
else if (pid < 0) {
// Error forking
perror("something bad happen");
} else {
// Parent process
//new process
setpgid(pid,pid);
newP.mPid = pid;
newP.completed = false;
mVector.push_back(newP);
if (background){//parent process because pid bigger than 0
wpid = waitpid(pid, &status, WUNTRACED);
}
else{
//wpid = waitpid(pid, &status, WNOHANG);
printf("%ld Started\n",pid);
}
}
}
}
}
int main()
{
initshell();
loop();
return 0;
}
/**
Was bedeutet Ausführung im Hintergrund?
Antwort: Es wird sofort weiter gearbeitet ohne dass auf den grade gestarteten Prozess gewartet wird.
Funktionsweise: Wir haben einen Loop, am Anfang wird eine Line von Terminal entgegengenommen, danach wird es in viele einzelne Token zerlegt (um space oder andere Zeichen zu vermeiden).
Und dann erstellen wir einen neuen Process mit fork().
Zombie: ist ein Prozess, der schon komplett durchgeführt wurde (completed execution), also bereits beendet sein sollte, aber immer noch einen Eintrag in der Prozesstabelle hat.
Vordergrundprozesse beziehen sich auf Anwendungen, die wir gerade ausführen und mit denen wir gerade interagieren. Dies gilt sowohl für grafische UI als auch für die Befehlszeile aka command line.
ps ax: https://man7.org/linux/man-pages/man1/ps.1.html
trasdasd: Hier wird error ausgeben weil execvp() = -1 ist.
Die einzige Aenderung die ich bemerke ist, dass das alte "ps ax" schon aus der Tabelle gelöscht wurde.
*/
  • waitpid(): on success, returns the process ID of the child whose state has changed; if WNOHANG was specified and one or more child(ren) specified by pid exist, but have not yet changed state, then 0 is returned. On error, -1 is returned

Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment