繁体   English   中英

在* nix中使用C启动异步进程

[英]Launching Asynchronous Processes using C in *nix

我有这样的情况:

start();
<Some code>
end();

我希望start()函数启动一个进程(不是单独的线程),该进程与父进程异步执行异步操作(这是指在生成该进程后,控件应立即返回到父级,并且该生成的进程在“后台”运行) ,再经过<Some code>块结束, end()函数将kill与相关联的进程id start() 我不确定如何执行此操作,尤其是使父代码块和子代码块异步的部分; 需要一些帮助。 谢谢。

编辑:在成员的帮助下,我能够编写此代码,但这有问题,如果有人可以指出错误,那就太好了。 我要_do_()要做的只是启动一个子进程,如果_stop_()无法将其杀死,则该子进程将永远不会结束。 但是由于某种原因,父进程会丢失,并且程序会在while()循环中无限期地运行。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> 
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <signal.h>
#include <errno.h>

pid_t id = 0;

int _do_()
{
//int status;
pid_t childpid; /* variable to store the child's pid */
FILE *fp= NULL;
childpid = fork();

//child stuff
if (childpid == 0) 
{
    id = getpid();
    fp = fopen ("Log.txt", "w+");
    while (1)
    {
        fprintf(fp, "Logging info...\n");
        fflush(fp);
    }
    fclose(fp);
}

if (childpid < 0) /* fork returns -1 on failure */
{
    perror("fork"); /* display error message */
    exit(-1); 
}

 return 0;

}

 //kill child process in _do_()
 int _stop_()
 {
  int en;
  printf("Going to kill child ID: %d\n", id);
  if (kill ( id , SIGKILL ) < 0)
  {
    en = errno;
    printf("Error while trying to KILL process: %s\n", strerror(en));
  }
  printf("Logging ended\n");

    return 0;

 }

 int main(int argc, char* argv[])
 {
   int i;

   _do_();
   for (i = 0; i < 200; i++)
    ;
   _stop_();
   printf("\nEnded...\n");
   return 0;
}

EDIT2:我无法做我想做的事情,杀死了一个从end() start()start()开始的进程,而是启动了一个守护进程,让它将值转储到文件上,直到文件大小达到某个预先指定的限制。 这是我想要的最接近的。

您想找到一些有关fork / exec / kill如何工作的示例。

通常,您会分叉一个进程,该进程将创建两个进程:一个子进程和一个父进程。 子进程从'fork'返回,返回码为0。父进程返回子进程的pid-这就是您是在子进程还是父进程中的方式。

现在,如果您要执行其他程序,则可以从子进程中调用“ exec”。 但是,您也可能具有以下代码:

pid = fork();
if (pid == 0)
{
  // do child stuff here
  exit (0);
}
if (pid == -1)
 // failed to fork, deal with it

// parent code goes here
...
...
kill(pid, SIGKILL); // you can kill your child process here if you want to.
                    // thanks to Adam Rosenfield for pointing out the signal number has to be sent

只要看一下教程就很简单。 Windows的工作原理有所不同,因此,如果您要将代码移植到Windows,请同时使用fork和exec,因为Windows实际上并不创建相同的程序副本-它实际上总是产生一个新程序。

与Windows程序员相比,Unix程序员比Windows程序员更倾向于使用线程,我相信,不要引述我的话,因为在Windows上创建新进程很重要。 在Unix上,这没什么大不了的,但是它比线程要大。 但是,相比之下,线程编程要困难得多,除非您真正需要它,否则您可能想远离它。

编辑:在执行“ kill(pid,SIGKILL)”之前,您真的要确保您的孩子还活着。 如果您的孩子死了,那么该pid可能会被另一个进程重用,在这种情况下,您可能会终止某个随机进程。

edit2:您的代码中有一个错误。

1 - remove 'int id...'
2 - move pid_t childpid; from function into global scope
3 - kill childpid, not 'id'

在“ //在此处做子代处理”部分中,您可能会第二次进行分叉并杀死原始子代进程,让子代继续运行,但现在已由init程序继承(进程ID 1)。 像这样:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>

void OutputPids(const char *tag)
{
    printf("in %s process %d, parent is %d\n", tag, getpid(), getppid());
}

int main(int ac, char **av)
{
    pid_t pid_child = -1;
    OutputPids("original");
    if(-1 == (pid_child = fork())) {
        perror("fork (for child)");
    } else if(0 == pid_child) {     /* fleeting child process */
        pid_t pid_grandchild = -1;
        if(-1 == (pid_grandchild = fork())) {
            perror("fork (for granchchild)");
        } else if(0 == pid_grandchild) { /* in grandchild */
            int i;
            setsid();
            setpgid(0, 0);
            for(i = sysconf(_SC_OPEN_MAX) ; i > 3 ; --i)
                close(i);  // close any stray filedescriptors
            OutputPids("grandchild(ready)");
            // run the rest of the command line as a asynch command
            execvp(av[1], av + 1);
            perror("execvp");
            exit(1);
        }
        OutputPids("child(suiciding)");
        _exit(0);           /* skip atexit processing, etc. */
    } else  {                   /* original process */
        OutputPids("original(waiting)");
        wait(pid_child);                /* wait for child to die (quick) */
    }
    OutputPids("original(after fork)");
    // stuff for your main routine continues here...
    sleep(2);
    OutputPids("original(done)");
    return 0;
}

示例运行:

$ ./doublefork echo GRANDCHILD OUTPUT
in original process 13414, parent is 22338
in original(waiting) process 13414, parent is 22338
in child(suiciding) process 13415, parent is 13414
in original(after fork) process 13414, parent is 22338
in grandchild(ready) process 13416, parent is 1
GRANDCHILD OUTPUT
in original(done) process 13414, parent is 22338
$

暂无
暂无

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

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