【发布时间】:2016-12-12 13:56:07
【问题描述】:
我正在制作自己的外壳,为什么不呢。 当您运行命令并以 & 结束时,该进程将在后台运行,因此我想创建一个 fg 命令,您可以使用该命令将后台进程置于前台。
我在制作 fg 函数时遇到了一些麻烦。 如果我理解正确,将 signal() 放在子进程中将使子进程接收信号。 Signal 接收两个参数,signum 和处理函数。 我们将使用 tcsetpgrp() 将给定的后台进程设置为前台。所以在 lsh_fg 我调用 tcsetpgrp(STDIN_FILENO, pid)。
所以 signum 应该是 sigttou 以便它可以接收来自 tcsetpgrp() 的信号。
我不知道应该在处理程序中放入什么,因为 tcsetpgrp() 应该按照手册页的描述进行操作: " 函数 tcsetpgrp() 使进程组具有进程组 ID pgrp 与 fd 关联的终端上的前台进程组 " 据我了解, tcsetpgrp() 正在向具有信号(sigttou,handler)的进程发送信号,该信号在收到信号时被置于前台。但我显然误解了这一点,因为它不起作用。
我的问题:我应该如何理解 tcsetpgrp() 和 signal(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;
}
【问题讨论】: