简体   繁体   English

如何在 Z6CE809EACF900BA125B40FABD90FABD90392E 中运行在 Z6CE809EACF900BA125B40FABD92E 中的 Z6CE809EACF900BA125Bshell 中编写一个 cp function (在 linux shell 中)

[英]how to write a cp function (in linux shell ) in c++ that runs in background?

I am trying to write a my own small linux shell, and i want to write the function cp , the function format is like the following: I am trying to write a my own small linux shell, and i want to write the function cp , the function format is like the following:

cp <old-file-path> <new-file-path>

It copies the first file into the second file (overwriting it), and if the second file doesn't exist it will create a new one.它将第一个文件复制到第二个文件中(覆盖它),如果第二个文件不存在,它将创建一个新文件。 If the files didn't open or any system call did not succeed it will print an error message.如果文件未打开或任何系统调用未成功,它将打印一条错误消息。 However, sometimes I want to copy large files so I want to run this cp command in the background (using fork without waiting for it to finish).但是,有时我想复制大文件,所以我想在后台运行这个cp命令(使用fork而不等待它完成)。

My problem is: how can I use fork and not wait for the process to finish?我的问题是:如何使用fork而不是等待进程完成? Currently, the child process becomes a zombie process.目前,子进程成为僵尸进程。

Here is my code:这是我的代码:

// num_args contains the number of arguments sent to cp
class CopyCommand : public BuiltInCommand {
 public:
  CopyCommand(const char* cmd_line) : BuiltInCommand(cmd_line){}
  virtual ~CopyCommand() {}
  void execute() override{
      if(this->num_args < 1){  // if no arguments were send to cp
          perror("invalid arguments");
          return;
      }
      char* buff;
      int fd1 = open(args[1], O_RDONLY);   
      if(fd1 == -1){
            perror("open failed");
            return;
      }
      if(this->num_args==2){          // copy file1 into file2 (overrite file 1)
          int fd2 = open(args[2], O_TRUNC);
            if (fd2 == -1) {                // if we couldn't open the file then create a new one (not sure if we supposed to this ?)
                fd2 = open(args[2], O_CREAT, 0666);
                if (fd2 == -1) {
                    perror("open failed");
                    return;
                }
            }
          pid_t PID = fork();
          if(PID == -1){
              perror("fork failed");
              return;
          }
          else if(PID == 0){

             // i need to use fork here :( before i start to write
            int read_res = read(fd1, &buff, 1);  /// read from the file fd1 into fd2
            while (read_res != -1) {
                if (!read_res) {
                    break;
                }
                if (write(fd2, buff, 1) == -1) {
                    perror("write failed");
                }
                read_res = read(fd1, buff, 1);
            }
            if (read_res == -1) {
                perror("read failed");
            }     
}   
      }
      else if(this->num_args==1){               // create file2 and copy file1 into file2

          // don't know how to do this yet 
          // i need to use fork here :(

      }
  }
};

For starters, I rewrote your code a bit.对于初学者,我稍微重写了您的代码。 In particular, note that the child branch (PID == 0) exits when it is done.特别要注意,子分支(PID == 0)在完成后退出。 The parent closes the passed-down file descriptors after forking and in case of error.父级在分叉后关闭传递的文件描述符,以防出错。

if (this->num_args == 2) {
    int fd1 = open(args[1], O_RDONLY);
    if (fd1 == -1) {
        perror("open failed");
        return;
    }

  int fd2 = open(args[2], O_TRUNC);
  if (fd2 == -1) {
    fd2 = open(args[2], O_CREAT, 0666);
    if (fd2 == -1) {
      perror("open failed");
      close(fd1);
      return;
    }
  }

  pid_t PID = fork();
  if (PID == -1) {
    perror("fork failed");
  } else if (PID == 0) {
    char buff[1024];
    int read_res = read(fd1, &buff, 1024); /// read from the file fd1 into fd2
    while (read_res != -1) {
      if (!read_res) {
        break;
      }
      if (write(fd2, buff, read_res) == -1) {
        perror("write failed");
      }
      read_res = read(fd1, buff, 1024);
    }
    if (read_res == -1) {
      perror("read failed");
    }
    exit(0);
  } else {
    printf("Copy running in background (pid: %d)\n", PID);
  }

  close(fd1);
  close(fd2);
  return
}

When the child process calls exit , the process will stick around in "Zombie" state.当子进程调用exit时,该进程将停留在“僵尸”state 中。 This state allows the parent process (you) to call wait or waitpid to retrieve the exit code.这个 state 允许父进程(你)调用waitwaitpid来检索退出代码。

As a secondary effect of the process ending, the kernel will send a SIGCHLD to your process, to let you know you can actually call wait without blocking.作为进程结束的次要效果,kernel 将向您的进程发送一个SIGCHLD ,让您知道您实际上可以调用wait而不会阻塞。 In your situation, you do not care about the exit code, so you can set up a "don't care" signal handler at the start of your program and let the kernel clean up the process:在您的情况下,您不关心退出代码,因此您可以在程序开始时设置“不关心”信号处理程序,并让 kernel 清理该过程:

signal(SIGCHLD, SIG_IGN);

This is documented in signal(2):这记录在信号(2)中:

If a process explicitly specifies SIG_IGN as the action for the signal SIGCHLD, the system will not create zombie processes when children of the calling process exit.如果进程明确指定 SIG_IGN 作为信号 SIGCHLD 的操作,则当调用进程的子进程退出时,系统不会创建僵尸进程。 As a consequence, the system will discard the exit status from the child processes.结果,系统将丢弃子进程的退出状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM