网络编程--守护进程

网络编程–堵塞式IO相关函数介绍

网络编程–探讨一些边界条件

网络编程–IO复用select和poll

本篇文章是阅读《UNIX网络编程卷1》的第13章的学习笔记,主要介绍了守护进程以及inetd超级服务器,本篇学习笔记还结合了《UNIX环境高级编程》中第9章和第13章的内容,从一些概念开始例如进程组、会话等等,接着给出创建守护进程的步骤以及代码示例、另外还会介绍LInux的日志系统、inetd守护进程作用流程。

终端登录流程

控制终端指的是键盘、显示器等等,当我们使用控制终端登录系统的时候,终端登录流程如下:

  1. 当系统启动时,内核创建进程ID为1的进程也就是init进程,init进程使系统进入多用户状态。init进程根据配置文件/etc/inittab确定需要打开哪些终端,对每一个允许登录的终端设备,init调用一次fork,它所生成的子进程则执行getty(exec)程序
  2. getty为终端设备调用open函数,以读写方式将终端打开,然后getty输出“longin:”之类的信息,并等待用户键入用户名

image-20220412224804021

  1. 当用户键入用户名后,getty工作完成。然后调用login程序:execle(“/bin/login”,”login”,”-p”,username,(char *)0,envp)
  2. 如果用户正确登录,login将会完成如下工作:
  • 将当前工作目录更改为该用户的起始目录
  • 调用chowm更改该终端的所有权,使登录用户成为他的所有者
  • 将对该终端设备的访问权限更改为用户读和写
  • 调用setgid及initgrops设置进程的组ID
  • 用login得到的所有信息初始化环境,起始目录,shell、用户名
  • login进程更改为用户登录的用户ID,并调用该用的登录shell

进程组、会话

进程组

每个进程除了有一个进程id之外,还属于一个进程组,进程组是一个会或多个机进程的集合,同一个进程组的各进程接受来自同一个终端的各种信号,每一个进程组有一个唯一的进程组ID,函数getpgrp返回调用者进程的进程组ID

#include <unistd.h>
pid_t getpgrp(void);

每个进程组都有一个组长进程,组长进程的进程组ID等于该进程ID,只要该进程组中有一个进程存在,则该进程组就存在,与其组长进程是否终止无关。

进程调用setpgid函数可以加入一个现有的进程组或者创建一个新的进程组

#include <unistd.h>
int setpdid(pid_d pid, pid_t pgid);
  • setpdid函数将pid进程的进程组ID设置为pgid
  • 如果这两个参数相等,则有pid指定的进程变成进程组组长,如果pid=0,则使用调用者的进程ID;pgid=0,则由pid指定的进程ID用作进程组ID
  • 一个进程只能为它自己或者它的子进程设置进程组ID

会话

会话是一个或多个进程组的集合,关系如图所示:

image-20220413083816762

进程调用setsid创建一个新的会话

#include <unistd.h>
pid_t setsid(void)

如果调用该函数的进程不是一个进程组的组长,则此函数会创建一个新的会话:

  • 该进程变成新会话的会话首进程
  • 该进程成为一个新进程组的组长
  • 该进程没有控制终端,如果在调用setsid之前该进程有控制终端,那么这种联系将会被切断

守护进程

守护进程是生存期长的一种进程,通常在系统装入时启动,仅在系统关闭时才终止,因为它们没有控制终端,所以它们是在后台运行的,使用ps -axj打印系统总各个进程的状态,-x表示显示没有控制终端的进程状态

image-20220413085735243

在ps的输出中,内核守护进程的名字出现在方括号内,该版本的Linux使用一个名为kthreadd的特殊进程来创建其他内核进程,守护进程的特点就是在后台运行,并且没有控制终端,并且大多数守护进程都以超级用户特权运行

编程规则

创建一个守护进程需要一下几个步骤:

  • 执行一个fork(),之后父进程退出,子进程继续执行,这样做的结果就是demaon成为了init的子进程,原因有两点:一是加入deamon是从命令行的一条简单的shell启动的,那么让父进程退出可以让shell认为这条命令已经执行结束,二是虽然子进程继承了父进程的进程组ID,但是子进程不是一个进程组的组长,而调用setsid的先决条件就是不是一个进程组的组长
  • setsid(),创建一个新的会话,结果有三个,(a)成为新会话的首进程,(b)成为一个新进程组的组长进程,©没有控制终端
  • 调用umask将文件模式创建屏蔽字设置为一个已知的值,通常是0,如果守护进程要创建文件,那么它可能要设置特定的权限
  • 将当前工作目录更改为根目录,从父进程继承过来的当前工作目录可能挂载在一个文件系统中,因为守护进程在系统关闭之前是一直存在的,如果守护进程的当前目录挂载在文件系统中,会导致该文件系统不能被卸载
  • 关闭不在需要的文件描述符,这让守护进程不在持有从其父进程继承而来的任何文件描述符
  • 调用openlog,使用syslogd来处理错误
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <syslog.h>

void start_daemon() {
    pid_t pid;
    const char *pname = "daemon";
    if((pid = fork()) < 0) {
        printf("Error: Fork");
        return;
    }else if(pid) {
        exit(0);
    }
    if(setsid() < 0){
        printf("Error: setsid");
        return;
    }

    if((pid = fork()) < 0) {
        printf("Error: Fork");
        return;
    }else if(pid){
        exit(0);
    }

    umask(0);
    chdir("/");
	//关闭文件描述符
	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);
    
    openlog(pname, LOG_PID, LOG_USER);

    //执行核心任务
	while(1){
		printf("daemon start");
		sleep(1);
	}

    return;

}
int main(void) {
    start_daemon();
}

syslog函数

syslogd守护进程是Linux用来记录设备日志的进程,由于守护进程没有控制终端,就不能将消息print到stderr上,所以从守护进程中登记消息的常用技巧就是使用syslog函数

#include <syslog.h>
void syslog(int priority, const char *message)

其中priority是级别(level)和设施(facility)两者的结合,level的值如下:

image-20220416100641588

facility的值如下:

image-20220416100730104

参考链接

《Unix网络编程》

《Unix环境编程》

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows守护进程(Windows Service)是在Windows操作系统上运行的后台进程,可以在系统启动时自动启动,并且在后台持续运行,提供某种服务或功能。与常规的应用程序不同,守护进程通常不与用户界面交互,而是在系统后台运行,无需用户登录或交互。 Windows守护进程可以执行各种任务,例如定期执行某些操作、提供网络服务、监控硬件设备等。它们可以通过Windows服务管理器进行配置和控制,可以设置为自动启动、手动启动或禁用。 开发Windows守护进程可以使用多种编程语言和开发框架,例如C++、C#、VB.NET等。在开发过程中,通常需要处理以下几个关键步骤: 1. 定义服务功能:确定守护进程需要提供的服务或功能,包括定义服务名称、描述、启动类型等。 2. 编服务代码:使用所选的编程语言和开发框架编守护进程的代码逻辑,包括启动、停止、暂停、恢复等操作。 3. 安装和配置服务:将守护进程安装到操作系统中,并进行必要的配置,例如设置启动类型、依赖关系等。 4. 控制和监控服务:使用Windows服务管理器或命令行工具来控制和监控守护进程的状态,例如启动、停止、暂停、恢复等操作。 需要注意的是,开发Windows守护进程需要一定的系统编程知识和理解操作系统的相关原理。在开发过程中,还需要考虑服务的稳定性、安全性和性能等方面的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值