3-1 一个最简单的服务器

3-2 Linux系统下的信号

图片.png
图片.png图片.png
Mac配置中文 man 手册
https://blog.csdn.net/monkeyhi/article/details/105317717

3-3 几个重要的信号

图片.png图片.png
图片.png图片.png

3-4 信号的发送与处理

图片.png
图片.png

testsig.cpp

  1. #include <iostream>
  2. #include <unistd.h>
  3. #include <signal.h>
  4. void sighandle(int sig)
  5. {
  6. std::cout << "sighup received :"
  7. << sig
  8. << std::endl;
  9. }
  10. int main(int argc,char **argv)
  11. {
  12. signal(SIGHUP, sighandle);
  13. signal(SIGINT, sighandle);
  14. signal(SIGQUIT, sighandle);
  15. pause();
  16. return 0;
  17. }

图片.png

3-5 通过 sigaction 安装信号

图片.png
testsigaction.cpp

  1. #include <iostream>
  2. #include <unistd.h>
  3. #include <signal.h>
  4. void sighandler(int sig){
  5. std::cout << "received signal: "
  6. << sig
  7. << std::endl;
  8. }
  9. int main(int argc, char *argv[])
  10. {
  11. struct sigaction act, oact;
  12. act.sa_handler = sighandler;
  13. sigfillset(&act.sa_mask);//掩码置位
  14. act.sa_flags = 0;
  15. sigaction(SIGINT, &act, &oact);
  16. pause();
  17. return 0;
  18. }

图片.png

3-6 以fork的方式创建后台进程

图片.png
图片.png

3-7 以daemon方式切换到后台

图片.png

daemon_api.cpp

  1. #include <unistd.h>
  2. #include <stdlib.h>
  3. int main(void)
  4. {
  5. if(daemon(0,0) == -1)
  6. exit(EXIT_FAILURE);
  7. while(1)
  8. {
  9. sleep(60);
  10. }
  11. return 0;
  12. }

图片.png

daemon.cpp

  1. //#include "apue.h"
  2. #include <stdio.h>
  3. #include <syslog.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <stdlib.h>
  7. #include <sys/resource.h>
  8. /**
  9. * 注释1:因为我们从shell创建的daemon子进程,所以daemon子进程会继承shell的umask,如果不清除的话,会导致daemon进程创建文件时屏蔽某些权限。
  10. * 注释2:fork后让父进程退出,子进程获得新的pid,肯定不为进程组组长,这是setsid前提。
  11. * 注释3:调用setsid来创建新的进程会话。这使得daemon进程成为会话首进程,脱离和terminal的关联。
  12. * 注释4:最好在这里再次fork。这样使得daemon进程不再是会话首进程,那么永远没有机会获得控制终端。如果这里不fork的话,会话首进程依然可能打开控制终端。
  13. * 注释5:将当前工作目录切换到根目录。父进程继承过来的当前目录可能mount在一个文件系统上,如果不切换到根目录,那么这个文件系统不允许unmount。
  14. * 注释6:在子进程中关闭从父进程中继承过来的那些不需要的文件描述符。可以通过_SC_OPEN_MAX来判断最高文件描述符(不是很必须).
  15. * 注释7:打开/dev/null复制到0,1,2,因为dameon进程已经和terminal脱离了,所以需要重新定向标准输入,标准输出和标准错误(不是很必须).
  16. */
  17. void daemonize(const char *cmd){
  18. int i, fd0, fd1, fd2;
  19. pid_t pid;
  20. //struct rlimit rl;
  21. //struct sigaction sa;
  22. /* * Clear file creation mask. */
  23. //umask(0);//注释1
  24. /* * Get maximum number of file descriptors. */
  25. //if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
  26. // err_quit("%s: can't get file limit", cmd);
  27. /* * Become a session leader to lose controlling TTY. */
  28. if ((pid = fork()) < 0) {//注释2
  29. printf("%s: can't fork", cmd);
  30. exit(-1);
  31. }
  32. else if (pid != 0) /* parent */
  33. exit(0);
  34. setsid();//注释3
  35. /* * Ensure future opens won't allocate controlling TTYs. */
  36. /*
  37. sa.sa_handler = SIG_IGN;
  38. sigemptyset(&sa.sa_mask);
  39. sa.sa_flags = 0;
  40. if (sigaction(SIGHUP, &sa, NULL) < 0)
  41. err_quit("%s: can't ignore SIGHUP", cmd);
  42. if ((pid = fork()) < 0)//注释4
  43. err_quit("%s: can't fork", cmd);
  44. */
  45. /*else if (pid != 0) *//* parent */
  46. /*
  47. exit(0);
  48. */
  49. /* * Change the current working directory to the root so * we won't prevent file systems from being unmounted. */
  50. if (chdir("/") < 0) {//注释5
  51. printf("%s: can't change directory to /", cmd);
  52. exit(-1);
  53. }
  54. /* * Close all open file descriptors. */
  55. /*
  56. if (rl.rlim_max == RLIM_INFINITY)
  57. rl.rlim_max = 1024;
  58. for (i = 0; i < rl.rlim_max; i++)
  59. close(i);//注释6
  60. */
  61. /* * Attach file descriptors 0, 1, and 2 to /dev/null. */
  62. fd0 = open("/dev/null", O_RDWR);//注释7
  63. //fd1 = dup(0);//注释7
  64. //fd2 = dup(0);//注释7
  65. dup2(fd0, STDIN_FILENO);
  66. dup2(fd0, STDOUT_FILENO);
  67. dup2(fd0, STDERR_FILENO);
  68. /* * Initialize the log file. */
  69. /*
  70. openlog(cmd, LOG_CONS, LOG_DAEMON);
  71. if (fd0 != 0 || fd1 != 1 || fd2 != 2) {
  72. syslog(LOG_ERR, "unexpected file descriptors %d %d %d",fd0, fd1, fd2);
  73. exit(1);
  74. }
  75. */
  76. }
  77. int main(int argc, char* argv[])
  78. {
  79. daemonize("test");
  80. while(1)
  81. {
  82. sleep(60);
  83. }
  84. }

daemon1.cpp

  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. void daemonize(){
  6. int fd0;
  7. pid_t pid;
  8. /* * Become a session leader to lose controlling TTY. */
  9. if ((pid = fork()) < 0) {//注释2
  10. printf("can't fork \n");
  11. exit(-1);
  12. }
  13. else if (pid != 0) /* parent */
  14. exit(0);
  15. setsid();//注释3
  16. if (chdir("/") < 0) {//注释5
  17. printf("can't change directory to / \n");
  18. exit(-1);
  19. }
  20. fd0 = open("/dev/null", O_RDWR);//注释7
  21. dup2(fd0, STDIN_FILENO);
  22. dup2(fd0, STDOUT_FILENO);
  23. dup2(fd0, STDERR_FILENO);
  24. }
  25. int main(int argc, char* argv[])
  26. {
  27. daemonize();
  28. while(1)
  29. {
  30. sleep(60);
  31. }
  32. }

deamon_impl.c

  1. #include <unistd.h>
  2. #include <signal.h>
  3. #include <sys/param.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <errno.h>
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <time.h>
  11. #include <syslog.h>
  12. void init_daemon(void)
  13. {
  14. int pid;
  15. int i;
  16. if(pid=fork())
  17. exit(0);//是父进程,结束父进程
  18. else if(pid< 0)
  19. exit(1);//fork失败,退出
  20. //是第一子进程,后台继续执行
  21. setsid();//第一子进程成为新的会话组长和进程组长
  22. //并与控制终端分离
  23. if(pid=fork())
  24. exit(0);//是第一子进程,结束第一子进程
  25. else if(pid< 0)
  26. exit(1);//fork失败,退出
  27. //是第二子进程,继续
  28. //第二子进程不再是会话组长
  29. for(i=0;i< NOFILE;++i)//关闭打开的文件描述符
  30. close(i);
  31. //chdir("/tmp");//改变工作目录到/tmp
  32. umask(0);//重设文件创建掩模
  33. return;
  34. }
  35. void sig_term(int signo)
  36. {
  37. if(signo==SIGTERM) /*catchedsignalsentbykill(1)command*/
  38. {
  39. syslog(LOG_INFO,"log4j-agent program terminated.");
  40. closelog();
  41. exit(0);
  42. }
  43. }
  44. int main(int argc, char** argv)
  45. {
  46. extern int errno;
  47. if (argc>1)
  48. {
  49. init_daemon();//初始化为Daemon
  50. openlog("log4j-agent", LOG_PID, LOG_USER);
  51. syslog(LOG_INFO, "log4j-agent started.");
  52. signal(SIGTERM,sig_term);/*arrangetocatchthesignal*/
  53. char *p[argc + 1];
  54. int j=0;
  55. for(j=0; j<argc+1; j++){
  56. p[j] = 0;
  57. }
  58. int i=1;
  59. for(i=1; i<argc; i++){
  60. p[i-1] = argv[i];
  61. }
  62. for(j=0; j<argc+1; j++){
  63. printf("%s \n", p[j]);
  64. }
  65. int ret = execvp(argv[1], p);
  66. if (ret<0){
  67. //syslog(LOG_ERR, "execl failed:%s");
  68. fprintf(stderr,"execl failed:%s", strerror(errno));
  69. return -1;
  70. }
  71. }else{
  72. printf("usage: ./daemon commond [argv] \n");
  73. printf("su as: ./daemon java -jar log4j-agent.jar -f conf/log4j.xml -p 4561 \n");
  74. }
  75. }