Linux程序设计入门 - fork, pthread, and signals 

  在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>  

  #include <stdlib.h>  

  #include <unistd.h>  

  void main(void)  

  {  

    pid_t pid;  

    printf("hello\n");  

    pid = fork();  

    switch (pid) {  

      case -1: printf("failure!\n"); break;  

      case  0: printf("I am child!\n"); break;  

      default: printf("my child is %d\n",pid); break;  

    }  

    for (;;) { /* do something here */ }  

  }  

  编译: 

  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>  

  #include <stdlib.h>  

  #include <unistd.h>  

  void main(void)  

  {  

    pid_t pid;  

    pid = fork();  

    if (pid>0) {  

      printf("daemon on duty!\n");  

      exit(0);  

    } else  

    if (pid<0) {  

      printf("Can't fork!\n");  

      exit(-1);  

    }  

    for (;;) {  

      printf("I am the daemon!\n");  

      sleep(3);  

      /* do something your own here */  

    }  

  }  

  编译: 

  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>  

  #include <stdlib.h>  

  #include <unistd.h>  

  void main(void)  

  {  

    FILE *fp;  

    pid_t pid;  

      exit(-1);  

    }  

    act.sa_handler = quit;  

    act.sa_flags   = 0;  

    sigemptyset(&act.sa_mask);  

    sigaction(SIGTERM,&act,NULL);  

    sigaction(SIGHUP,&act,NULL);  

    sigaction(SIGINT,&act,NULL);  

    sigaction(SIGQUIT,&act,NULL);  

    sigaction(SIGUSR1,&act,NULL);  

    sigaction(SIGUSR2,&act,NULL);  

    for (;;) {  

      sleep(3);  

    }  

  }  

  编译: 

  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  

GNU FORK PTHREAD SIGNALS的更多相关文章

  1. Cross-platform Tools

    MinGW和Cygwin都解决了C++跨平台交叉编译的问题,使Linux下的程序在Windows上编译运行成为可能. MinGW给习惯在Linux上开发的人员在windows上提供了一套类似的工具集: ...

  2. cygwin-介绍-安装

    初学linux时,最头疼的是,因为windows和linux各有优点,各有用途,所以只能麻烦的在两者之间切换,不断的重启.开机时也麻烦,因为初学者大多数使用windows,装了linux后,开机会自动 ...

  3. [cross compile]cygwin和mingw

    转自:http://blog.csdn.net/embededvc/article/details/6829010 1. MinGW和CygWin/gcc概念 Unix下编译通过的C代码,在win32 ...

  4. mingw64环境搭建

    转自:http://www.cr173.com/soft/132367.html MinGW64位版,默认编译出来是64位的,需要编译32位请使用-m32 参数!mingw是一款gnu工具集合是Min ...

  5. Android学习之一:Cygwin简介

    为了能够一窥Android底层的东东,还是要搭建编译Android的环境.虽有Ubuntu和Suse系统,无奈总感觉在不同的系统下切来切去很是不便.在Windows工作学习,要编译Android,就不 ...

  6. win7 下使用cygwin

    http://cygwin.com/index.html      还是看官网! 很多用windows的朋友不习惯于用linux的开发环境.虽然很乐意尝试一下,但是往往怕 linux系统打乱了自己的正 ...

  7. cygwin,在win中开发linux程序

    cygwin,在win中开发linux程序 http://www.cygwin.cn/site/info/show.php?IID=1001  很多用windows的朋友不习惯于用linux的开发环境 ...

  8. Cygwin、MinG、MSys区别与联系(转)

    转自:https://www.biaodianfu.com/cygwin-ming-msys.html 什么是Cygwin? Cygwin,原Cygnus出品(已被红帽收购),目前是RedHat名下的 ...

  9. Cygwin使用2-心得

    引用:http://www.jb51.net/article/6236.htm 1.在cygwin里访问Windows盘 cd /cygdrive/c cd c: 2.整合cygwin命令到Windo ...

随机推荐

  1. (一)Windows下搭建PHP开发环境及相关注意事项

    PHP集成开发环境有很多,如XAMPP.AppServ......只要一键安装就把PHP环境给搭建好了.但这种安装方式不够灵活,软件的自由组合不方便,同时也不利于学习.所以我还是喜欢手工搭建PHP开发 ...

  2. java对象数组的概述和使用

    1 public class Student 2 { 3 // 成员变量 4 private String name; 5 private int age; 6 7 // 构造方法 8 public ...

  3. WinForm中关于控件焦点的问题

    方法一: 在打开一个窗体时,我们往往需要设置焦点让光标出现在我们希望它出现的位置上. 这时我们可以在窗体的Activated事件中设置焦点 例如我们希望光标在打开窗体的时候出现在textBox1上,我 ...

  4. [RxJS] Transformation operator: repeat

    Operator repeat() is somewhat similar to retry(), but is not for handling operators. In this lesson ...

  5. mysql使用硬链接配合truncate 删除2.2T的表 --杨奇龙

    http://blog.csdn.net/wyzxg/article/details/8626814 http://blog.itpub.net/22664653/viewspace-750408/ ...

  6. React Links

    Tutorial: https://hulufei.gitbooks.io/react-tutorial/content/jsx-in-depth.html

  7. ubuntu 14.04 64位 下 编译安装MySQL 5.7.11

    步骤一: 先去mysql的官方网站 去down 编译源码包 mysql 网址:www.mysql.com downloads  (MySQL Community Server) 下载版本选择  sou ...

  8. ZOJ 3905 Cake(贪心+dp)

    动态规划题:dp[i][j]表示有i个Cake,给了Alice j个,先按照b排序,这样的话,能保证每次都能成功给Alice Cake,因为b从大到小排序,所以Alice选了j个之后,Bob最少选了j ...

  9. 未能加载文件或程序集“Newtonsoft.Json, Version=4.5.0.0[已解决]

    在使用百度UEditor,不小心将Newtonsoft.Json,升级了,然后就报的一个错,说: 其他信息: 未能加载文件或程序集“Newtonsoft.Json, Version=4.5.0.0, ...

  10. 用GitHub Pages免费空间搭建Blog

    前言   其实之前就知道可以用GitHub Pages搭建静态博客,不过之前一直忙着爬手册撸代码==,昨天终于把前端各种手册里的入门教程撸的差不多了(CSS布局撸的我要吐了好嘛),于是把代码什么的放一 ...