会话:
概念:多个进程组的集合
- 创建一个会话需要注意以下6点
- 调用进程不能是进程组组长,创建会话的创始人不能是进程组组长,该进程变成新会话首进程(session headler)
- 该进程成为一个新进程组的组长进程
- 需有root权限,ubuntu不需要
- 新会话丢弃原有的控制终端,该会话没有控制终端
- 若该调用进程是组长进程,则出错返回
- 建立新会话时,先调用fork,父进程终止,子进程调用setsid,,,因为组长进程不能创建会话,而父进程默认是组长进程
- getsid函数:传一个进程id返回一个会话id
获取进程所属的会话ID
pid_t getsid(pid_t pid);
成功,返回调用进程的会话ID;失败返回-1,设置errno
pid为0表示查看当前进程session ID
ps ajx
命令查看系统中的进程,参数a表示不仅列出当前用户的进程,也列出其他用户的进程,参数x表示不仅列除控制终端的进程,也列出所有无控制终端的进程,参数j表示列出与作业控制相关的信息
组长进程不能成为新会话首进程,新会话首进程必定会成为组长进程
- setsid函数:创建一个会话
创建一个会话,并以自己的ID设置进程组ID,同时也是新会话的ID
pid_t setsid(void)
成功返回调用进程的会话ID;失败返回-1,设置errno
调用了setsid函数的进程,即是新的会长,也是新的组长
守护进程创建步骤分析
一、守护进程概念:
Daemon(精灵)进程,是Linux中的后台服务进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。 一般采用以d结尾的名字
Linux后台的一些系统服务进程,没有控制终端,一般不能直接和用户交互,不受用户登陆、注销的影响,一直在运行着,他们都是守护进程,如:预读入缓冲机制的实现,ftp服务器,nfs服务器等
创建守护进程,最关键的一步是调用setsid函数创建一个新的session,并成为session leader
二、 守护进程创建步骤分析
1,fork子进程,让父进程终止
2,子进程调用setsid()创建新会话
3,通常根据需要,改变工作目录位置chdir()
4,根据需要,重设umask文件权限掩码
5,根据需要,关闭/重定向 文件描述符
6,守护进程,业务逻辑。while()
守护进程创建
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/stat.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc, char *argv[])
{
pid_t pid;
int ret;//这个变量总是用来接收函数返回值,判断函数是否成功运行
int fd;//文件描述符
//1,创建子进程,终止父进程
pid = fork();
if(pid>0)
eixt(0);
//2,创建新会话
pid = setsid();
if(pid == -1)
sys_err("setsid error");
//3,改变工作目录
ret = chdir("/home/study/Linux");
if(ret == -1)
sys_err("chdir error");
//4,设置umask权限掩码
umask(0022);//改变文件访问权限掩码755
//5,关闭或重定向文件描述符,重定向到空洞中
close(STDIN_FILENO);//关闭文件描述符0
fd = open("/dev/null",O_RDWR);//fd---->0,用的是文件描述符中最小的
if(fd == -1)
sys_err("open error");
dup2(fd,STDOUT_FILENO);//重定向 stdout和stderr
dup2(fd,STDERR_FILENO);
//6, 业务逻辑
while(1);//模拟守护进程业务
return 0;
}
运行是在终端上是无反应的,因为运行在后端,可以用ps aux或 ps ajx
注销用户也是不影响进程的,只能kill掉