守护进程
先了解一些基本概念:
进程组:
一个或多个进程的集合,如父子进程或者通过管道连接起来的进程等这些都同属一个进程组。进程组id一般都是该进程组的组长id。
进程组中所有进程死亡,进程组才算结束。
ctrl+c 发送信号,发送给的是进程组,组内所有进程都会退出
ctrl+c信号不能发给后台进程
作业:
正在执行的进程称为作业,一个作业通常包含一个或多个进程,这几个进程共同完成一项任务,就叫作业。
尤其是使用了管道或重定向命令时,一个作业就同时启动多个进程。
shell分前后台控制的不是进程而是作业或者进程组,前后台作业都可以由多个进程组成,shell可同时运行一个前台作业和多个后台作业,这就是作业控制
作业与进程组的区别:
如果作业中的某个进程又创建了子进程,则子进程不属于作业。一旦作业运行结束,Shell就把自己提到前台,如果原来的前台进程还存在(如果这个子进程还没终止),它自动变为后台进程组。
-
进程和作业:
联系:
一个作业通常包括几个进程,几个进程共同完成一个任务,即作业。
区别:
jobs命令:查看后台作业
fg命令:将后台作业提到前台来执行
bg命令:将作业放在后台执行,使前台执行其他任务
在指令后添加&也有同样效果。
会话:
会话(session)是一个或多个进程组的集合。每打开一个终端,就新建了一个会话,一个会话对应一个终端
一个会话中可以有多个进程组,会话结束所有进程组都终止
守护进程:
也叫精灵进程。
守护进程是脱离于终端并且在后台运行的进程。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。
在linux或者unix操作系统中在系统引导的时候会开启很多服务,这些服务就叫做守护进程。
常年在后台服务,不与其他用户进行交互
Linux中大多服务器进程都是守护进程 ftp服务器、web服务器等
守护进程还能完成许多系统任务,例如,作业规划进程crond、打印进程lqd等(这里的结尾字母d就是Daemon的意思)。
如果想让某个进程不因为用户或终端或其他地变化而受到影响,那么就必须把这个进程变成一个守护进程。
创建守护进程:
因为关掉终端进程就会结束,因此创建守护进程不能和终端有关系,不受终端影响
首先第一步:新启一个会话 setsid()函数用于创建一个新的会话
当该函数要求调用它的函数不是一个进程组的组长
所以我们要先创建一个子进程fork(),父进程退出,然后在子进程中调用setsid()函数
调用结束后,当前进程成为新的会话的组长,当前进程id成为session_id,它自成一个进程组,进程组的组长也是他。此时没有控制终端
要关闭所有已打开的文件描述符
- 方式1:for( int i=0;i<=255;i++ )
close(i);
- 方式2:讲文件描述符dup到空洞文件
空洞文件:/dev/null
放进空洞文件的内容都不存在了
推荐方式1,可以再拿出来用
最后再编写我们需要守护进程执行的任务即可
假如我们可以让守护进程定期扫描一个文件,并执行该文件中的命令,再将执行结果写入另一个文件中。
计划任务:可将脚本、程序或文档安排在某个时间运行,它在每次启动windows系统的时候自动启动并在后台运行。
setup 命令:打开系统服务
守护进程的工作目录一定在某个磁盘下,经过一段时间有可能磁盘坏掉了,我们就需要卸载掉这个磁盘,
可由于该磁盘下有守护进程一直在运行,导致无法卸载,所以我们就需要改变它的当前路径到根目录下来解决这个问题。根文件系统不能被卸载.
所以要创建守护进程一般需要进行以下五步:
1.创建子进程 fork()
2.新启一个会话 setsid()
3.关闭所有文件描述符
4.更改当前路径到根目录下
chdir(”/”)
5.写要执行的动作
简单实现一个守护进程,他的功能就是每秒向文件中打个” . “
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
if(fork()>0)
{
exit(0);
}
setsid();//创建守护进程
int i;
for(i=0;i<255;i++)
close(i);
int fd=open("tmp",O_RDWR|O_CREAT,0644);
for(;;)
{
write(fd,".",1);
sleep(1);
}
close(fd);
}
系统提供了一个函数来代替以上几步:
int deamon( int nochdir,int noclose);
nochdir: 0表示更改到根目录,非0不更改
noclose: 0表示将标准输入、输出、错误重定向到/dev/null,非0不重定向
用该函数来实现一把:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
daemon(0,0);
for(;;)
{
write(fd,".",1);
sleep(1);
}
close(fd);
}
文章最后发布于: 2018-08-11 13:00:48
相关阅读
进程和线程的区别 进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。
MFC隐藏进程自身(任务管理器不可见,wSysCheck等工具可见
MFC隐藏进程只要把cpp和h加入工程,include就可以了。 代码地址: //------------------HideProcess.h-------------------- //
提升进程权限-OpenProcessToken等函数的用法 GetCurrentProcessID 得到当前进程的ID OpenProcessToken 得到进程的令牌句柄 Lo
清除陷入CLOSE_WAIT的进程,而不清除父进程的方法,理论上来说是可行的,但是有可能引起相关组件不能正确显示状态数据。比如,使用Apache
进程间通信的方式大概有以下几种: 共享内存:顾名思义,共享内存就是两个进程同时共享一块内存,然后在这块内存上的数据可以共同修改