2016-12-12 5 views
2

Я делаю свою собственную оболочку причиной, почему, черт возьми, нет. Когда вы запускаете команду и завершаете ее с помощью &, процесс запускается в фоновом режиме, поэтому я хотел бы сделать команду fg, которую вы можете использовать, чтобы поместить фоновый процесс на передний план.сигнал переднего плана tcsetpgrp c

У меня есть некоторые проблемы, делающие функцию fg. Если я понимаю это правильно, то посылка сигнала() в дочернем процессе позволит дочернему процессу получать сигнал. Сигнал получает два аргумента, signum и функцию обработчика. Мы собираемся использовать tcsetpgrp() для установки заданного фонового процесса на передний план. Поэтому в lsh_fg я вызываю tcsetpgrp (STDIN_FILENO, pid).

Таким образом, signum должен быть сигтотом, чтобы он мог получать сигнал от tcsetpgrp().

Я не знаю, что надо ставить внутри обработчика, так как tcsetpgrp() должен делать, как страница человека описывает его: " Функция tcsetpgrp() делает группу процессов с процессом групповой ID pgrp группа процесса переднего плана на терминале, связанная с fd « Как я понимаю, tcsetpgrp() посылает сигнал процессу с сигналом (sigttou, handler), который выдается на передний план, когда он его получает. Но я явно неправильно понял это, так как он не работает.

Мои вопросы: Как я должен понимать, как работают tcsetpgrp() и сигнал (sigttou, handler)? И что должен включить мой обработчик? Я очень ценю ваши ответы, потому что я действительно застрял здесь :-) Посмотрите мой код: Ps: Я новичок в программировании на C и в системе, и это мое первое сообщение, так что любая конструктивная критика в отношении моего кода приветствуется Большое спасибо: D

#include <sys/wait.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <signal.h> 

pid_t pid; 

int toke_c; 
//function declaration for the function pointers 
int lsh_cd(char **args); 
int lsh_pwd(char **args); 
int lsh_exit(char **args); 
int lsh_fg(char **args); 

//An array of functions: 
int (*builtin_func[]) (char **) = { 
    &lsh_cd, 
    &lsh_pwd, 
    &lsh_exit, 
    &lsh_fg 
}; 

//An array of the given strings: 
char *builtin_str[] = { 
    "cd", 
    "pwd", 
    "exit", 
    "fg" 
}; 

///built in functions cd and pwd 

int lsh_fg(char **args){ 
tcsetpgrp(STDIN_FILENO, pid); 
    return 1; 
} 

void fg_handler() 
{ 
//What to put here??? 
} 

///built in functions cd and pwd 
int lsh_cd(char **args) 
{ 
    if (args[1] == NULL) { 
    fprintf(stderr, "lsh: cd: no arguments given\n"); 
    } else { 
    if (chdir(args[1]) != 0) { 
     perror("lsh"); 
    } 
    } 
    return 1; 
} 

int lsh_pwd(char **args) 
{ 
char * cwd; 
    cwd=getcwd (NULL,0); 
    printf ("%s\n ", cwd); 
    return 1; 
} 

int lsh_exit(char **args) 
{ 
    return 0; 
} 

/* Handlers Here*/ 
void killer() 
{ 
    if (pid == 0) 
    exit(0); 
} 

void handler() 
{ 
    //I DON'T KNOW WHAT TO PUT HERE 
} 

int lsh_launch(char **args) 
{ 

    int status=0; 
    pid = fork(); 
    if (pid == 0) { 
    // child process 
    signal(SIGINT, killer); 
    if (execvp(args[0], args) == -1) { 
     fprintf(stderr,"Command not found in $PATH\n"); 
    } 
    return 1; 
    } else if (pid < 0) { 
    //error 
    perror("lsh"); 
    } else { 
    // parent 
    signal(SIGINT, killer); 
    waitpid(pid, &status, WUNTRACED); 
    } 
    return 1; 
} 

int lsh_background(char **args) 
{ 

    pid_t pid; 
    int status=0; 
    pid = fork(); 
    if (pid == 0) { 
    // child process 
    setpgid(0, 0); 
    signal(SIGINT, killer); 
    signal(SIGTTOU, fg_handler); 
    if (execvp(args[0], args) == -1) { 
     fprintf(stderr,"Command not found in $PATH\n"); 
    } 
    return 1; 
    } else if (pid < 0) { 
    //error 
    perror("lsh"); 
    } else { 
    // parent 
    signal(SIGTTOU, fg_handler); 
    signal(SIGINT, killer); 
    } 
    return 1; 
} 

//if a command was entered that we've been using 
int lsh_exec(int argc, char **args) 
{ 
    int i; 
    if (args[0] == NULL) {return 1;} 
    int tresh=4; 

    char **args1=malloc(toke_c*sizeof(char *)); 
    int j; 
    for(j=0;j<toke_c-1;j++){ 
     args1[j]=args[j]; 
    } 

    if(strcmp(args[toke_c-1],"&")==0){ 
     return lsh_background(args1); 
     } 

     for (i = 0; i < tresh; i++) { 
     if (strcmp(args[0], builtin_str[i]) == 0) { 
     return (*builtin_func[i])(args); 
     } 
    } 

    return lsh_launch(args); 
} 

#define MAX_STR 256 

//reading the line 
char *lsh_lread(void) 
{ 
    char *str = malloc (MAX_STR); 
    fgets (str, MAX_STR, stdin); 
} 

//tokenizer 
char **lsh_tokenizer(char *line) 
{ 
    int bufsize = 64; 
    int pos_t = 0; 
    char **tokens = malloc(bufsize * sizeof(char*)); 
    char *token; 
    token = strtok(line, " \t\r\n\a"); 

    while (token != NULL) { 
    tokens[pos_t] = token; 
    pos_t++; 

    token = strtok(NULL, " \t\r\n\a"); 
    } 
    tokens[pos_t] = NULL; 
    toke_c=pos_t; 

    return tokens; 
} 


void lsh_loop(void) 
{ 
    int argc; 
    char *line; 
    char **args; 
    int status; 

    do { 
    printf(">> "); 
    line = lsh_lread(); 
    args = lsh_tokenizer(line); 
    status = lsh_exec(argc,args); 
    free(line); 
    free(args); 
    } while (status); 
} 


int main(int argc, char **argv) 
{ 
    lsh_loop(); 

    return 0; 
} 

ответ

1

Как я должен понять путь tcsetpgrp() и сигнал (SIGTTOU, обработчик) работать вместе?

В ваших целях это не так. Вам не нужно посылать процессу сигнал, чтобы сделать его группу процессов главной группой pgroup (но см. Ниже). На самом деле, я не понимаю, почему вы когда-либо намеренно отправляли SIGTTOU группе процессов, которую вы пытаетесь поставить на передний план.

Вот центральная часть POSIX's documentation for tcsetpgrp() (подчеркивание добавлено):

Если процесс имеет контрольный терминал, устанавливает tcsetpgrp() переднего плана идентификатор группы процесса, связанного с терминалом для pgid_id. Приложение должно гарантировать, что файл, связанный с fildes, является управляющим терминалом вызывающего процесса, а управляющий терминал в настоящее время связан с сеансом вызывающего процесса. Приложение должно гарантировать, что значение pgid_id соответствует идентификатору группы процессов процесса в том же сеансе, что и вызывающий процесс.

Попытки использовать tcsetpgrp()из процесса, который является членом группы фонового процесса на fildes, связанный с его управляющим терминалом должен вызывать группа процессов, которые будут отправлена ​​в SIGTTOU сигнале. [...]

Речь идет об осуществлении команды fg. Основная полезность такой команды: interactive, и если процесс (т. Е. ваша оболочка) принимает эту команду в интерактивном режиме, то он должен находиться в группе процессов переднего плана, потому что это единственная группа процессов, которая получает входные данные из Терминал. Предположим, что такой процесс вызывает функцию и что аргументы удовлетворяют их индивидуальным требованиям, эффект «tcsetpgrp() должен установить идентификатор группы переднего плана, связанный с терминалом, до pgid_id». Конечно, нет. Никакая сигнализация не документирована, чтобы согласиться с этим.

SIGTTOU приходит в эту картину, только если tcsetpgrp() вызывается процессом, который находится в фоне процесса группу. Если я реализую оболочку, я бы склонен отключить управление заданиями для оболочек, работающих в фоновом режиме (команда завершилась с ошибкой). Обработчик по умолчанию для этого сигнала останавливает процесс (не то же самое, что завершает); это подходит для фонового процесса, который пытается записать на управляющий терминал своего сеанса. Аналогично, SIGTTIN по умолчанию останавливает процесс и доставляется в фоновые процессы, которые пытаются считывать из управляющего терминала его сеанса.

Для fg команды, вы не ожидаете или хотите обрабатывать SIGTTOU или SIGTTIN, , но это не значит, что вам не нужно, чтобы сигнализировать. Скорее, процесс (изначально переднего плана), который вызывает tcsetpgrp(), должен после этого отправить SIGCONT в новую наземную pgroup в случае остановки некоторых или всех этих процессов, что вполне возможно. Обработчик по умолчанию для этого сигнала возобновляет процесс, если он остановлен, что именно вы хотите.

Короче говоря, вам, вероятно, не нужно вообще писать какие-либо пользовательские обработчики сигналов для этой цели.

Смежные вопросы