守护进程是在后台运行不受终端控制的进程(如输入、输出等),一般的网络服务都是以守护进程的方式运行。守护进程脱离终端的主要原因有两点:(1)用来启动守护进程的终端在启动守护进程之后,需要执行其他任务。(2)(如其他用户登录该终端后,以前的守护进程的错误信息不应出现)由终端上的一些键所产生的信号(如中断信号),不应对以前从该终端上启动的任何守护进程造成影响。要注意守护进程与后台运行程序(即加&启动的程序)的区别。

 创建守护进程的过程:  

1. 调用fork创建子进程。父进程终止,让子进程在后台继续执行。
2. 子进程调用setsid产生新会话期并失去控制终端调用setsid()使子进程进程成为新会话组长和新的进程组长,同时失去控制终端。
3. 忽略SIGHUP信号。会话组长进程终止会向其他进程发该信号,造成其他进程终止。
4. 调用fork再创建子进程。子进程终止,子子进程继续执行,由于子子进程不再是会话组长,从而禁止进程重新打开控制终端。
5. 改变当前工作目录为根目录。一般将工作目录改变到根目录,这样进程的启动目录也可以被卸掉。
6. 关闭打开的文件描述符,打开一个空设备,并复制到标准输出和标准错误上。 避免调用的一些库函数依然向屏幕输出信息。
7. 重设文件创建掩码清除从父进程那里继承来的文件创建掩码,设为0。
8. 用openlog函数建立与syslogd的连接。

创建守护进程的例子如下程序所示:

void daemon_init(const char* pname,int facility)
{int                 i;pid_t               pid;struct  rlimit      rl;struct  sigaction   sa;/* 清除文件模式创建掩码,使新文件的权限位不受原先文件模式创建掩码的权限位的影响*/umask(0);if(getrlimit(RLIMIT_NOFILE,&rl) < 0){perror("getrlimit() error");exit(-1);}if((pid = fork()) < 0){perror("fork() error");exit(-1);}else if(pid > 0)   /*父进程终止 */exit(0);setsid();         /* 子进程成为会话首进程*/sa.sa_handler = SIG_IGN;sigemptyset(&sa.sa_mask);sa.sa_flags = 0;if(sigaction(SIGHUP,&sa,NULL) < 0){perror("sigaction() error");exit(-1);}if((pid = fork()) < 0){perror("fork() error");exit(-1);}else if(pid > 0)exit(0);        /* 第一个子程进终止,保证后面操作不会分配终端 */if(chdir("/")<0)    /* 改变工作目录 */{perror("chdir() error");exit(-1);}if(rl.rlim_max == RLIM_INFINITY)rl.rlim_max = 1024;for(i=0;i<rl.rlim_max;++i)  /*关闭所有打开的文件描述字*/close(i);openlog(pname, LOG_PID, facility);  /*用syslogd处理错误*/
}

现在要用守护进程实现一个时间服务器,呈现的功能是:服务器运行后自动成为守护进程,返回shell;客户端运行后收到服务器发来的当前时间。

时间服务器程序(timeserver.c)如下:

View Code

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 #include <errno.h>
  6 #include <sys/types.h>
  7 #include <fcntl.h>
  8 #include <signal.h>
  9 #include <syslog.h>
 10 #include <sys/resource.h>
 11 #include <sys/socket.h>
 12 #include <netinet/in.h>
 13 #include <arpa/inet.h>
 14 #include <time.h>
 15
 16 #define MAXLINE 100
 17
 18 void daemon_init(const char* pname,int facility)
 19 {
 20     int                 i;
 21     pid_t               pid;
 22     struct  rlimit      rl;
 23     struct  sigaction   sa;
 24     /* 清除文件模式创建掩码,使新文件的权限位不受原先文件模式创建掩码的权限位的影响*/
 25     umask(0);
 26     if(getrlimit(RLIMIT_NOFILE,&rl) < 0)
 27     {
 28         perror("getrlimit() error");
 29         exit(-1);
 30     }
 31     if((pid = fork()) < 0)
 32     {
 33         perror("fork() error");
 34         exit(-1);
 35     }
 36     else if(pid > 0)   /*父进程终止 */
 37         exit(0);
 38     setsid();         /* 子进程成为会话首进程*/
 39     sa.sa_handler = SIG_IGN;
 40     sigemptyset(&sa.sa_mask);
 41     sa.sa_flags = 0;
 42     if(sigaction(SIGHUP,&sa,NULL) < 0)
 43     {
 44         perror("sigaction() error");
 45         exit(-1);
 46     }
 47     if((pid = fork()) < 0)
 48     {
 49         perror("fork() error");
 50         exit(-1);
 51     }
 52     else if(pid > 0)
 53         exit(0);        /* 第一个子程进终止,保证后面操作不会分配终端 */
 54     if(chdir("/")<0)    /* 改变工作目录 */
 55     {
 56         perror("chdir() error");
 57         exit(-1);
 58     }
 59     if(rl.rlim_max == RLIM_INFINITY)
 60         rl.rlim_max = 1024;
 61     for(i=0;i<rl.rlim_max;++i)  /*关闭所有打开的文件描述字*/
 62         close(i);
 63     openlog(pname, LOG_PID, facility);  /*用syslogd处理错误*/
 64 }
 65
 66 int main(int argc,char *argv[])
 67 {
 68     int                 listenfd, connfd;
 69     socklen_t           addrlen, len;
 70     struct sockaddr     cliaddr;
 71     struct sockaddr_in  server;
 72     char                buff[MAXLINE];
 73     time_t              ticks;
 74     int                 n;
 75     bzero(&server, sizeof(server));
 76     bzero(&cliaddr,sizeof(cliaddr));
 77     server.sin_family = AF_INET;
 78     server.sin_port = htons(5050);
 79     server.sin_addr.s_addr = htonl(INADDR_ANY);
 80     daemon_init(argv[0], 0);
 81     if((listenfd=socket(AF_INET, SOCK_STREAM, 0))==-1)
 82     {
 83         syslog(LOG_NOTICE|LOG_LOCAL0,"socket error");
 84         exit(-1);
 85     }
 86     if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr))==-1)
 87     {
 88         syslog(LOG_NOTICE|LOG_LOCAL0,"socket error");
 89         exit(-1);
 90     }
 91     if(listen(listenfd,5)==-1)
 92     {
 93         syslog(LOG_NOTICE|LOG_LOCAL0,"listen error");
 94         exit(-1);
 95     }
 96     for ( ; ; )
 97     {
 98         len = sizeof(cliaddr);
 99         connfd = accept(listenfd,&cliaddr, &len);
100         ticks = time(NULL);
101         snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
102         if((n= write(connfd, buff, strlen(buff)))==-1)
103            syslog(LOG_NOTICE|LOG_LOCAL0,"write error");
104         close(connfd);
105     }
106 }

客户端程序(timeclient.c)如下:

View Code

 1 #include <unistd.h>
 2 #include <sys/socket.h>
 3 #include <netinet/in.h>
 4 #include <netdb.h>
 5 #include <stdio.h>
 6 #include <stdlib.h>
 7 #include <string.h>
 8 #define PORT            5050
 9 #define MAXDATASIZE     100
10
11 int main(int argc, char *argv[])
12 {
13     int                  fd, numbytes;
14     char                 buf[MAXDATASIZE];
15     struct sockaddr_in   server;
16     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
17     {
18         perror("Create socket failed.");
19         exit(-1);
20     }
21     bzero(&server, sizeof(server));
22     server.sin_family = AF_INET;
23     server.sin_port = htons(PORT);
24     server.sin_addr.s_addr = htonl(INADDR_ANY);
25     if (connect(fd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1)
26     {
27         perror("connect failed.");
28         exit(-1);
29     }
30     if( ((numbytes = recv(fd, buf, MAXDATASIZE, 0)) == -1))
31     {
32         perror("recv error.");
33         exit(-1);
34     }
35     buf[numbytes] ='\0';
36     printf("Server Message: %s\n",buf);
37     close(fd);
38 }

程序运行过程: 先运行时间服务器程序,再在运行客户端程序。

运行时间服务器程序结果如下:

此时timeserver是个守护进程,已经在运行,通过ps -axj命令可以查看该进程,查看结果如下:

运行客户端程序结果如下:

客户端收到服务器发送的当前时间。

转载于:https://www.cnblogs.com/Anker/archive/2012/12/20/2826568.html

守护进程实现时间服务器相关推荐

  1. php守护进程热更新,服务器编程--守护进程

    守护(Daemon)进程又叫作"精灵进程",虽然守护进程这个名字更为常用,但是个人感觉还是精灵进程较为机灵可爱些.服务器进程一般都是守护进程,这类进程的一个显著特点就是无交互地在后 ...

  2. java 守护进程 linux_Java实现Linux下服务器程序的双守护进程

    一.简介 现在的服务器端程序很多都是基于Java开发,针对于Java开发的Socket程序,这样的服务器端上线后出现问题需要手动重启,万一大半夜的挂了,还是特别麻烦的. 大多数的解决方法是使用其他进程 ...

  3. linux c 守护进程创建原理及简易方法

    1:什么是Linux下的守护进程 Linux daemon是运行于后台常驻内存的一种特殊进程,周期性的执行或者等待trigger执行某个任务,与用户交互断开,独立于控制终端.一个守护进程的父进程是in ...

  4. 《APUE》读书笔记—第十三章守护进程

    守护进程也称为精灵进程是一种生存期较长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件.他们常常在系统引导装入时启动,在系统关闭时终止.unix系统有很多守护进程,大多数 ...

  5. 深入理解Linux守护进程

    深入理解Linux守护进程Linux服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台的守护进程(daem ...

  6. Linux 守护进程创建原理及简易方法

    1:什么是Linux下的守护进程 Linux daemon是运行于后台常驻内存的一种特殊进程,周期性的执行或者等待trigger执行某个任务,与用户交互断开,独立于控制终端.一个守护进程的父进程是in ...

  7. Linux守护进程设计规范及python实现

    http://blog.csdn.net/mr_jj_lian/article/details/7252222 守护进程 守护进程是生存期长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待 ...

  8. < Linux > 守护进程

    目录 1.守护进程 守护进程的概念 进程组和会话 2.守护进程化的方式 TCP网络程序(守护进程化) TCP网络程序(守护进程化)gitee地址 daemon创建守护进程 nohup命令 1.守护进程 ...

  9. 总结]关于守护进程解释文章

    [总结]关于守护进程解释文章 这里三篇文章涵盖了守护进程的功能和一些解释,可以为准备优化系统启动速度的朋友提供一些建议.第一篇中还有设置硬盘等等的信息资料.欢迎大家阅读.摘自linuxsir.org ...

最新文章

  1. NC:自体免疫水泡皮肤病中鉴定基因与微生物组互作(微生物组关联分析MWAS)
  2. 镜像公测招募啦!!!用镜像开通云服务器,限时免费体验!!
  3. django中的ajax_post请求
  4. 云计算年度技术盛典,腾讯Techo Park开发者大会将在京召开
  5. 利用Minst数据集训练原生GAN网络
  6. android工厂测试开发,Android开机启动工程测试APK功能开发
  7. 机器学习入门(1、特征抽取)
  8. php 7.4 编译安装
  9. Vue的8种通信方式
  10. Android应用上架国内各大应用市场对应用Logo、应用截图要求整理
  11. 2014Gartner技术成熟度曲线
  12. 大数据岗位更看重学历还是工作经验?
  13. Apache Camel源码研究之Language
  14. 数据库设计 一对多 多对多 无限级菜单 设计方法
  15. Arduinojson官网序列化示例教程
  16. 2012年广州市户口搭户指南——可以搭到朋友家里?
  17. 中级工程师如何走向高级
  18. notepad转换json_Notepad++的Json格式化插件
  19. 计算机软硬件故障排除知识,计算机软硬件基础知识及常见故障排除方法(精选).doc...
  20. Infinite redirect in navigation guard 死循环

热门文章

  1. 微信知识付费小程序博客源码(带299条数据)
  2. 很好看的加载跳转网站源码
  3. SQL 2005 with(nolock)详解
  4. CNNIC公告称半个月已处理不良网站域名万例
  5. 如何建立MSSQL数据库
  6. Linux Shell 编程实战技巧
  7. #!/bin/sh与#!/bin/bash的区别
  8. UITableView 系列四 :项目中行的操作 (添加移动和删除)(实例)
  9. 5个常用的htaccess技巧
  10. reids的持久化 RDB和AOF