简体   繁体   中英

Launching Asynchronous Processes using C in *nix

I have a situation like this:

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

I want start() function to launch a process (not separate threads) that does something asynchronously (by that I mean immediately after spawning the process, the control should return to parent and the spawned process going in 'background') with the parent process, and then after <Some code> block finishes, end() function would kill the process id associated with start() . I am not sure how to do this, especially the part to make parent and child code blocks asynchronous; need some help. Thanks.

EDIT: After getting help from the members, I was able to write this code, but this has problems, it would be great if someone could point out the errors. All I want for _do_() is to initiate a child process, which could never end if _stop_() is unable to kill it. But for some reason the parent process is getting lost and the program runs indefinitely on the while() loop.

#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: I couldn't do what I wanted, killing a process started at start() from end() , instead launched a daemon process and let it dump values on a file till the filesize reached to some pre-specified limit. This is the nearest to what I wanted.

You want to find some samples regarding how fork/exec/kill work.

normally you fork a process, which creates two processes: a child and a parent. The child returns from 'fork' with return code 0. The parent process returns pid of child - that's how you know if you're in child or parent.

Now if you want to execute some other program, you can call 'exec' from child process. However you might as well have code like:

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

It's simple once you look at a tutorial on it. Windows works differently, so if you want to port your code to windows, use both fork and exec, as windows doesn't actually create an identical copy of program - it actually always spawns a new program.

I believe, don't quote me, than windows programmers tend to use threads more than unix programmers - as creating a new process on windows is a big deal. On unix it's not as big of a deal, but it's bigger deal than a thread. But thread programming is so much harder, in comparison, you probably want to stay away from it unless you really really need it.

edit: before doing 'kill(pid, SIGKILL)', you really want to make sure your child is still alive. If your child died, the pid might have gotten reused by another process, in which case you may terminate some random process.

edit2: There's a bug in your code.

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

In the "// do child stuff here" section, you might fork a second time and kill the original-child process, letting the grandchild continue, but now inherited by the init program (process ID 1). Something like this:

#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;
}

Example run:

$ ./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
$

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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