2012-04-01 32 views
0

我有這樣的情況:即做一些事情異步啓動在* nix中採用C異步進程

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

我想start()功能啓動一個進程(不是單獨的線程)(由我產卵後,立即指進程,控制應該返回到父進程和產生的進程在'後臺')與父進程,然後<Some code>塊完成後,end()函數將killstart()相關聯的進程ID。 我不知道如何做到這一點,尤其是使父代碼和子代碼塊異步的部分;需要一些幫助。謝謝。

編輯:在得到成員的幫助之後,我能夠編寫這段代碼,但是這有問題,如果有人能指出錯誤,那將會很棒。所有我想要的_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:我不能做什麼,我想,殺的過程開始於start()end(),而是推出了一個守護進程,讓它在文件上,直到達到某個預先指定的限制文件大小傾倒值。這是最接近我想要的。

+0

什麼操作系統? – 2012-04-01 23:54:00

+0

請參閱[這個SO問題](http://stackoverflow.com/q/7794273/960195) - 它包含實現'start'的代碼,它要求'end'的代碼。 – 2012-04-01 23:57:02

+0

Linux系統... – Sayan 2012-04-01 23:57:57

回答

4

你想找到一些關於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上創建新進程是一件大事。在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' 
+0

謝謝,特別是編輯和一個很好的總結 – Sayan 2012-04-02 00:20:44

+1

+ 1,但是迂腐,它是'kill(pid,SIG)'(而不是'kill(pid)'),其中'SIG'是信號的名稱你想發送,在這種情況下可能是'SIGKILL'。 – 2012-04-02 00:40:40

+0

我有一個問題,在開始(),我有兩個部分,一個爲孩子另一個父母,我退出父母,但不是從孩子。然後,在'end()'我發出一個'kill(pid,SIGKILL)',其中pid是一個全局變量,以便我得到孩子的pid。但不知怎的,孩子仍然活着...... – Sayan 2012-04-02 00:53:30

1

在「//這裏做孩子的東西」一節中,你可能會fork一個第二次殺死原,子進程,讓孫子繼續,但現在由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 
$