Linux程式設計入門 – fork, pthread, and signals

來源:互聯網
上載者:User
 

  在UNIX程式設計中,學會fork及signal的運用,算是相當基本的功夫。  
 
   
  fork()及signal經常運用在daemon守護神這一類常駐程式,另外像 
   
  a4c.tty/yact/chdrv這些中文終端機程式也有用到,一般如 
   
  Mozilla/Apache/Squid等大程式幾乎都一定會用到。  
 
   
  雖然在UNIX下的程式寫作,對thread的功能需求並非很大,但thread在現代的 
   
  作業系統中,幾乎都已經存在了。pthread是Linux上的thread函數庫,如果您 
   
  要在Linux下撰寫多線程式,例如MP3播放程式,熟悉pthread的用法是必要的。 
 
   
  pthread及signal都可以用一大章來討論。在這裡,我只談及最簡單及常用的技 
   
  巧,當您熟悉這些基本技巧的運用後,再找一些專門深入探討pthread及signal 
   
  程式寫作的書籍來研究。這些進階的寫法,用到的機會較少,將層次分明,學 
   
  習速度應該會比較快。  
 
 
   
  程式分歧fork() 
 
   
  fork()會產生一個與父程式相同的子程式,唯一不同之處在於其process 
   
  id(pid)。  
 
   
  如果我們要撰寫守護神程式,或是例如網路伺服器,需要多個行程來同時提供 
   
  多個連線,可以利用fork()來產生多個相同的行程。  
 
   
  函數宣告 
 
   
  pid_t fork(void);  
   
  pid_t vfork(void);  
 
   
  傳回值: 
 
   
  -1 : 失敗。  
   
    0 : 子程式。  
   
  >0 : 將子程式的process id傳回給父程式。  
 
   
  在Linux下fork()及vfork()是相同的東西。  
 
   
  範例一: fork.c 
 
   
  在這個範例中,我們示範fork()的標準用法。  
 
   
  #include <stdio.h> </p><p> #include <stdlib.h> </p><p> #include <unistd.h> </p><p> void main(void) </p><p> { </p><p> pid_t pid; </p><p> printf("hello/n"); </p><p> pid = fork(); </p><p> switch (pid) { </p><p> case -1: printf("failure!/n"); break; </p><p> case 0: printf("I am child!/n"); break; </p><p> default: printf("my child is %d/n",pid); break; </p><p> } </p><p> for (;;) { /* do something here */ } </p><p> }<br />  
   
  編譯: 
 
   
  gcc -o ex1 fork.c  
 
   
  執行結果: 
 
   
  ./ex1 &  
 
   
  hello  
   
  my child is 8650  
   
  I am child!  
 
   
  我們可以見到,使用fork(),可將一個程式分岐成兩個。在分歧之前的程式碼 
   
  只執行一次。  
 
   
  檢驗行程: 
 
   
  ps | grep ex1  
 
   
   8649  p0 R    0:40 ./ex1  
   
   8650  p0 R    0:40 ./ex1  
 
   
  8649是父程式的pid,8650則為子程式的pid。  
   
  您會需要用到"killall ex1"來殺掉兩個行程。  
 
   
  範例二: daemon.c 
 
   
  在UNIX中,我們一般都利用fork(),來實作所謂的"守護神程式",也就是DOS中 
   
  所謂的"常駐程式"。一般的技巧是將父程式結束,而子程式便成為"守護神"。  
 
   
  這個範例中,示範一般標準的daemon寫法。  
 
   
  #include <stdio.h> </p><p> #include <stdlib.h> </p><p> #include <unistd.h> </p><p> void main(void) </p><p> { </p><p> pid_t pid; </p><p> pid = fork(); </p><p> if (pid>0) { </p><p> printf("daemon on duty!/n"); </p><p> exit(0); </p><p> } else </p><p> if (pid<0) { </p><p> printf("Can't fork!/n"); </p><p> exit(-1); </p><p> } </p><p> for (;;) { </p><p> printf("I am the daemon!/n"); </p><p> sleep(3); </p><p> /* do something your own here */ </p><p> } </p><p> } </p><p>    
  編譯: 
 
   
  gcc -o ex2 daemon.c  
 
   
  執行結果: 
 
   
  ./ex2  
 
   
  daemon on duty!  
   
  I am the daemon!  
   
  接下來每三秒鐘,都會出現一個"I am the daemon!"的訊息,這表示您的程式 
   
  已經"長駐"在系統中了。  
 
   
  檢驗行程: 
 
   
  ps | grep ex2  
 
   
  8753  p0 S    0:00 ./ex2  
 
   
  注意到在範例一中,我們下的指令為"./ex1 &",而在範例二中為"./ex2",沒 
   
  有"&"符號。  
   
     
 
   
  範例三: lock.c 
 
   
  許多的時候,我們希望"守護神"在系統中只有一個,這時候會需要用到pid 
   
  lock的技巧。如果您注意到/var/run目錄中的內容,您會發現到有許多的*.pid 
   
  檔,觀看其內容都是一些數字,這些數字其實就是該行程的pid。  
 
   
#include <stdio.h> </p><p> #include <stdlib.h> </p><p> #include <unistd.h> </p><p> void main(void) </p><p> { </p><p> FILE *fp; </p><p> pid_t pid; </p><p> exit(-1); </p><p> } </p><p> act.sa_handler = quit; </p><p> act.sa_flags = 0; </p><p> sigemptyset(&act.sa_mask); </p><p> sigaction(SIGTERM,&act,NULL); </p><p> sigaction(SIGHUP,&act,NULL); </p><p> sigaction(SIGINT,&act,NULL); </p><p> sigaction(SIGQUIT,&act,NULL); </p><p> sigaction(SIGUSR1,&act,NULL); </p><p> sigaction(SIGUSR2,&act,NULL); </p><p> for (;;) { </p><p> sleep(3); </p><p> } </p><p> }<br />  
   
  編譯: 
 
   
  gcc -o ex1 lock.c  
 
   
  執行 
 
   
  ./ex1  
 
   
  daemon on duty!  
 
   
  送訊號 
 
   
  我們先找出該守護神程式的pid  
 
   
  PID=`cat /var/run/lock.pid`  
 
   
  接下來利用kill來送訊號  
 
   
  kill $PID  
 
   
  Receive signal 15  
 
   
  程式將會結束,並且/var/run/lock.pid將會被刪除掉,以便下一次daemon再啟 
   
  動。注意到如果quit函數內,沒有放exit(),程式將永遠殺不掉。  
 
   
  接下來送一些其它的訊號試試看。  
   
  ./ex1  
   
  PID=`cat /var/run/lock.pid`  
   
  kill -HUP $PID  
 
   
  Receive signal 1  
 
   
  您可以自行試試  
   
  kill -INT $PID  
   
  kill -QUIT $PID  
   
  kill -ILL $PID  
   
  .  
   
  .  
   
  .  
   
  等等這些訊號,看看他們的結果如何。  
 
   
  訊號的定義 
 
   
  在/usr/include/signum.h中有各種訊號的定義  
   
  #define SIGHUP          1       /* Hangup (POSIX).  */  
   
  #define SIGINT          2       /* Interrupt (ANSI).  */  
   
  #define SIGQUIT         3       /* Quit (POSIX).  */  
   
  #define SIGILL          4       /* Illegal instruction (ANSI).  */  
   
  #define SIGTRAP         5       /* Trace trap (POSIX).  */  
   
  #define SIGABRT         6       /* Abort (ANSI).  */  
   
  #define SIGIOT          6       /* IOT trap (4.2 BSD).  */  
   
  #define SIGBUS          7       /* BUS error (4.2 BSD).  */  
   
  #define SIGFPE          8       /* Floating-point exception (ANSI).  
   
  */  
   
  #define SIGKILL         9       /* Kill, unblockable (POSIX).  */  
   
  #define SIGUSR1         10      /* User-defined signal 1 (POSIX).  */ 
 
   
  #define SIGSEGV         11      /* Segmentation violation (ANSI).  */ 
 
   
  #define SIGUSR2         12      /* User-defined signal 2 (POSIX).  */ 
 
   
  #define SIGPIPE         13      /* Broken pipe (POSIX).  */  
   
  #define SIGALRM         14      /* Alarm clock (POSIX).  */  
   
  #define SIGTERM         15      /* Termination (ANSI).  */  
   
  #define SIGSTKFLT       16      /* ??? */  
   
  #define SIGCLD          SIGCHLD /* Same as SIGCHLD (System V).  */  
   
  #define SIGCHLD         17      /* Child status has changed (POSIX).  
   
  */  
   
  #define SIGCONT         18      /* Continue (POSIX).  */  
   
  #define SIGSTOP         19      /* Stop, unblockable (POSIX).  */  
   
  #define SIGTSTP         20      /* Keyboard stop (POSIX).  */  
   
  #define SIGTTIN         21      /* Background read from tty (POSIX).  
   
  */  
   
  #define SIGTTOU         22      /* Background write to tty (POSIX).  
   
  */  
   
  #define SIGURG          23      /* Urgent condition on socket (4.2 
   
  BSD).  */  
   
  #define SIGXCPU         24      /* CPU limit exceeded (4.2 BSD).  */  
   
  #define SIGXFSZ         25      /* File size limit exceeded (4.2 
   
  BSD).  */  
   
  #define SIGVTALRM       26      /* Virtual alarm clock (4.2 BSD).  */ 
 
   
  #define SIGPROF         27      /* Profiling alarm clock (4.2 BSD).  
   
  */  
   
  #define SIGWINCH        28      /* Window size change (4.3 BSD, Sun). 
   
    */  
   
  #define SIGPOLL         SIGIO   /* Pollable event occurred (System 
   
  V).  */  
   
  #define SIGIO           29      /* I/O now possible (4.2 BSD).  */  
   
  #define SIGPWR          30      /* Power failure restart (System V).  
   
  */  
   
  #define SIGUNUSED       31  
 
   
  函數宣告: 
 
   
  Signal Operators  
 
   
       int sigemptyset(sigset_t *set);  
   
       int sigfillset(sigset_t *set);  
   
       int sigaddset(sigset_t *set, int signum);  
   
       int sigdelset(sigset_t *set, int signum);  
   
       int sigismember(const sigset_t *set, int signum);  
 
   
  Signal Handling Functions  
 
   
       int sigaction(int signum,  const  struct  sigaction  *act,struct 
   
       sigaction *oldact);  
   
       int  sigprocmask(int  how,  const  sigset_t *set, sigset_t 
   
       *oldset);  
   
       int sigpending(sigset_t *set);  
   
       int sigsuspend(const sigset_t *mask);  
 
   
  Structure Signal Action  
   
  struct sigaction {  
   
                   void (*sa_handler)(int);  
   
                   sigset_t sa_mask;  
   
                   int sa_flags;  
   
                   void (*sa_restorer)(void);  
   
               }  
   
     
 
 
 
   
  OK STATION, Webmaster, Brian Lin  
   
     
   
   轉自:http://docs.huihoo.com/gnu/linux1/tutorial4.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.