Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
前景信号tcsetpgrp c_C_Unix - Fatal编程技术网

前景信号tcsetpgrp c

前景信号tcsetpgrp c,c,unix,C,Unix,我在做我自己的外壳,为什么不呢。 当您运行一个命令并以&结束它时,进程将在后台运行,因此我想生成一个fg命令,您可以使用它将后台进程置于前台 我在做fg功能时遇到了一些问题。 如果我理解正确,将signal()放入子进程将使子进程接收信号。 信号接收两个参数,signum和handler函数。 我们将使用tcsetpgrp()将给定的后台进程设置为前台。所以在lsh_fg中,我调用tcsetpgrp(STDIN_FILENO,pid) 因此signum应该是sigtou,以便它可以接收来自tcs

我在做我自己的外壳,为什么不呢。 当您运行一个命令并以&结束它时,进程将在后台运行,因此我想生成一个fg命令,您可以使用它将后台进程置于前台

我在做fg功能时遇到了一些问题。 如果我理解正确,将signal()放入子进程将使子进程接收信号。 信号接收两个参数,signum和handler函数。 我们将使用tcsetpgrp()将给定的后台进程设置为前台。所以在lsh_fg中,我调用tcsetpgrp(STDIN_FILENO,pid)

因此signum应该是sigtou,以便它可以接收来自tcsetpgrp()的信号

我不知道应该在处理程序中放置什么,因为tcsetpgrp()应该按照手册页的描述执行: " 函数tcsetpgrp()使进程组具有进程组ID pgrp与fd关联的终端上的前台进程组 " 据我所知,tcsetpgrp()正在向具有信号的进程(sigttoo,handler)发送一个信号,该进程在接收到信号时被置于前台。但我显然误解了这一点,因为它不起作用

我的问题:我应该如何理解tcsetpgrp()和信号(sigttoo,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;
}
#包括
#包括
#包括
#包括
#包括
#包括
pid_t pid;
国际托克劳;
//函数指针的函数声明
int lsh_cd(字符**args);
int lsh_pwd(字符**args);
int lsh_出口(字符**args);
int lsh_fg(字符**args);
//一系列函数:
int(*内置函数[])(字符**)={
&lsh_cd,
&lsh_pwd,
&lsh_出口,
&lsh_fg
};
//给定字符串的数组:
字符*内置字符[]={
“cd”,
“pwd”,
“退出”,
“前景”
};
///内置功能cd和pwd
int lsh_fg(字符**args){
tcsetpgrp(标准文件号,pid);
返回1;
}
void fg_handler()
{
//在这里放什么???
}
///内置功能cd和pwd
int lsh_cd(字符**参数)
{
if(args[1]==NULL){
fprintf(stderr,“lsh:cd:未给出参数\n”);
}否则{
if(chdir(args[1])!=0){
佩罗(“lsh”);
}
}
返回1;
}
int lsh_pwd(字符**args)
{
char*cwd;
cwd=getcwd(NULL,0);
printf(“%s\n”,cwd);
返回1;
}
int lsh_出口(字符**args)
{
返回0;
}
/*这里的处理程序*/
空虚杀手()
{
如果(pid==0)
出口(0);
}
void处理程序()
{
//我不知道该在这里放什么
}
int lsh_启动(字符**args)
{
int status=0;
pid=fork();
如果(pid==0){
//子进程
信号(SIGINT,killer);
if(execvp(args[0],args)=-1){
fprintf(stderr,“在$PATH中找不到命令\n”);
}
返回1;
}否则如果(pid<0){
//错误
佩罗(“lsh”);
}否则{
//母公司
信号(SIGINT,killer);
waitpid(pid和状态,WUNTRACED);
}
返回1;
}
int lsh_背景(字符**args)
{
pid_t pid;
int status=0;
pid=fork();
如果(pid==0){
//子进程
setpgid(0,0);
信号(SIGINT,killer);
信号(SIGTTOU、fg_处理器);
if(execvp(args[0],args)=-1){
fprintf(stderr,“在$PATH中找不到命令\n”);
}
返回1;
}否则如果(pid<0){
//错误
佩罗(“lsh”);
}否则{
//母公司
信号(SIGTTOU、fg_处理器);
信号(SIGINT,killer);
}
返回1;
}
//如果输入了我们一直在使用的命令
int lsh_exec(int argc,char**args)
{
int i;
如果(args[0]==NULL){return 1;}
int-tresh=4;
char**args1=malloc(toke_c*sizeof(char*));
int j;
对于(j=0;j
我应该如何理解tcsetpgrp()和信号(sigttoo,handler)一起工作的方式

出于您的目的,它们不需要。您不需要向进程发送信号以使其进程组成为前台pgroup(但请参见下文)。事实上,我不明白您为什么会故意向您试图放置在前台的进程组发送
sigttoo

以下是本文的中心部分(强调部分):

如果进程有一个控制终端,
tcsetpgrp()
应将与终端关联的前台进程组ID设置为
pgid\u ID
。应用程序应确保与
fildes
关联的文件是呼叫进程的控制终端,并且控制终端当前与呼叫进程的会话关联。应用程序应确保
pgid\u id
的值与调用进程所在会话中进程的进程组id匹配

在与其控制终端相关联的
fildes
上,尝试从作为后台进程组成员的进程中使用
tcsetpgrp()
,将导致进程组发送一个
SIGTTOU
信号。[…]

您所说的是实现一个
fg
命令。这种命令的主要用途是交互式执行,如果是进程(即shell)如果以交互方式接收该命令,则它必须位于前台进程组中,因为这是从终端接收输入的唯一进程组。那么,假设这样的进程调用函数,并且参数满足其各自的要求,则效果为“
tcsetpgrp()
应将与终端相关的前台进程组ID设置为
pgid\u ID
”或失败,当然。没有记录与此相关的信号

只有在后台进程组中的进程调用了
tcsetpgrp()
时,
sigttoo
才会出现在这张图片中。如果我实现了一个shell,我倾向于禁用后台运行的shell的作业控制(命令将失败并出现错误)。默认处理程序