C语言实现守护进程

news/2024/11/28 13:30:46/

C语言实现守护进程

守护进程(daemon)是在后台运行的一种特殊进程,它没有控制终端,通常用于在系统启动时启动一些需要常驻后台的服务程序。

Linux的大多数服务器就是用守护进程的方式实现的。如web服务器进程http等。守护进程在后台运行,类似于Windows中的系统服务。

查看系统中的进程:

ps axj

参数a表示不仅列当前用户的进程,也列出所有其他用户的进程,
参数x表示不仅列有控制终端的进程,也列出所无控制终端的进程,
参数j表示列出与作业控制相关的信息。

凡是TPGID一栏写着-1的都是没有控制终端的进程,也就是守护进程。在COMMAND一列用[]括起来的名字表示内核线程,这些线程在内核里创建,没有用户空间代码,

因此没有程序文件名和命令行, 通常采用以k开头的名字,表示Kernel。守护进程通 常采用以d结尾的名字,表示Daemon。

守护进程的原理是通过fork()创建一个子进程,让子进程脱离控制终端,设置新的会话组,关闭标准输入输出和错误输出,最后通过umask()函数来设置文件的权限掩码,使得守护进程在运行过程中不会被其他用户所访问。

daemon()守护进程函数

原型

int daemon(int nochdir,int noclose)

其中,nochdir参数用于指定是否改变工作目录,如果给它传递0,则工作目录将被设置为“/”(根目录),否则继续使用当前工作目录。

noclose参数为0时,标准输入、标准输出和标准错误输出都被重定向到/dev/null文件,否则依然使用原来的设备。

该函数成功时返回0,失败返回-1,并设置errno。
例如:
daemon(0,0):nochdir为0 改为根目录,noclose为0 关闭所有文件描述符;

将当前工作目录更改为根目录的作用:
防止当前目录有一个目录被删除,导致守护进程无效。
使用fork()创建的子进程是继承了父进程的当前工作目录,由于在进程运行中,当前目录所在的文件系统是不能卸载的,这对以后使用会造成很多的麻烦。

因此通常的做法是让“/”作为守护进程的当前目录,当然也可以指定其他的别的目录来作为守护进程的工作目录。

以下是用C语言实现守护进程的完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>void daemonize()
{pid_t pid;/* Step 1: Create a child process */pid = fork();if(pid < 0) /* Error occurred */{perror("fork");exit(1);}if(pid > 0) /* Parent process, exit */{printf("Parent process: %d\n", pid);exit(0);}/* Step 2: Create a new session */if(setsid() == -1){perror("setsid");exit(1);}/* Step 3: Change working directory */if(chdir("/") == -1){perror("chdir");exit(1);}/* Step 4: Set file permissions */umask(0);/* Step 5: Close all open file descriptors */close(STDIN_FILENO);close(STDOUT_FILENO);close(STDERR_FILENO);
}int main()
{daemonize();/* Do daemon work here */while(1){/* Do something */}return 0;
}

在上面的代码中,daemonize()函数用于创建守护进程。首先通过fork()函数创建一个子进程,然后让子进程调用setsid()函数创建一个新的会话组,使得守护进程与原来的终端完全隔离。接着调用chdir()函数将当前工作目录设置为根目录,防止守护进程占用当前工作目录的文件系统导致该文件系统无法卸载。调用umask()函数设置文件创建权限掩码,确保守护进程创建的文件权限不会被其他用户访问。最后,关闭所有的文件描述符,防止程序在后台运行时产生意料之外的输出。

在调用了daemonize()函数之后,守护进程就开始后台运行了。通常情况下,守护进程会执行一些长期运行的任务,如网络连接、消息队列、数据备份等等。

该文章会更新,欢迎大家批评指正。

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
服务器课程:C++服务器


http://www.ppmy.cn/news/109770.html

相关文章

【Linux网络服务】Apache配置与应用

Apache配置与应用 一、构建虚拟Web主机1.1httpd服务支持的虚拟主机类型包括以下三种 二、基于域名的虚拟主机三、基于IP地址的虚拟主机四、基于端口的虚拟机五、Apache连接保持六、构建Web虚拟目录与用户授权限制七、日志分割 一、构建虚拟Web主机 虚拟Web主机指的是在同一台服…

制作嵌入式busybox rootfs系统

1、busybox下载 BusyBox 此篇使用版本BusyBox 1.31.1 (stable) 2、设置交叉编译环境变量 source environment-setup-aarch64-poky-linux或者其他架构的编译链工具 3、busybox编译设置 cd busybox-1.31.1 修改根目录Makefile中的CROSS_COMPILE和ARCH参数 比如ARCH ? ar…

基于ChatGPT的文本生成

ChatGPT是一种基于Transformer的自然语言处理模型&#xff0c;能够生成自然而流畅的文本序列。在文本生成领域&#xff0c;ChatGPT模型具有非常广泛的应用&#xff0c;可以用于实现文本摘要、文本生成、翻译等多种任务。 一、模型架构 基于ChatGPT的文本生成模型与基于ChatGP…

创建第一个.NET MAUI应用

1.打开VS2022,创建新项目,并选择.NET MAUI应用,然后点击下一步 2.输入项目相关配置,然后点击下一步 3. 选择框架版本,然后点击创建 4.项目创建成功后会自动打开概述页 5.平台框架切换 6.启动应用,如有下图提示,启动开发者模式 成功启动应用 7.修改应用 修改MainPage.xml如下图…

手写一个webpack插件(plugin)

熟悉 vue 和 react 的小伙伴们都知道&#xff0c;在执行过程中会有各种生命周期钩子&#xff0c;其实webpack也不例外&#xff0c;在使用webpack的时候&#xff0c;我们有时候需要在 webpack 构建流程中引入自定义的行为&#xff0c;这个时候就可以在 hooks 钩子中添加自己的方…

Java性能权威指南-总结2

Java性能权威指南-总结2 性能测试方法原则2:理解批处理流逝时间、吞吐量和响应时间批处理流逝时间吞吐量测试 原则3:用统计方法应对性能的变化 性能测试方法 原则2:理解批处理流逝时间、吞吐量和响应时间 性能测试的第2条原则是多角度审视应用性能。应该测量哪个指标取决于对…

python+django高校人事管理系统vue

本高校人事管理系统以Django作为框架&#xff0c;Python语言&#xff0c;B/S模式以及MySql作为后台运行的数据库。本系统主要包括以下功能模块&#xff1a;用户、院长、职称申报、工资信息、绩效信息、奖惩信息、招聘、科系分类等模块。 本文着重阐述了高校人事管理系统的分析、…

LeetCode 560 和为 K 的子数组

LeetCode 560 和为 K 的子数组 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/subarray-sum-equals-k/description 博主Github&#xff1a;https://github.com/GDUT-Rp/LeetCode 题目&#xff1a; 给你一个整数数组 …