一、进程组和会话
进程组
- 多个进程的集合,每个进程都属于一个进程组,简化对多个进程的管理,waitpid函数和kill函数的参数中用到
- 父进程创建子进程的时候默认父子进程属于同一进程组。进程组的ID==第一个进程ID(组长进程),组长进程id==进程组id,组长进程可以创建一个进程组,创建该进程组中的进程,然后终止。
- 只要有一个进程存在,进程组就存在,生存期与组长进程是否终止无关
- kill -SIGKILL -进程组id 杀掉整个进程组
- 一个进程可以为自己或子进程设置进程组
会话
多个进程组的集合
创建会话的6点注意事项:
- 调用进程不能是进程组组长,该进程变成新会话首进程(平民)
- 该进程成为一个新进程组的组长进程
- 需要root权限(ubuntu不需要)
- 新会话丢弃原有的控制终端,该会话没有控制终端
- 该调用进程是组长进程,则出错返回
- 建立新会话时,先调用fork,父进程终止,子进程调用setsid
多个进程就是一个进程组,而多个进程组就是一个会话,组长进程不能创建会话
getsid函数:
pid_t getsid(pid_t pid);
功能:
获取进程所属的会话ID
成功返回所属会话ID,失败返回-1并设置error
setsid函数:
pid_t setsid();
功能:
创建一个会话,并以自己的ID设置进程组ID,同时也是新会话的ID
成功返回调用进程的会话ID,失败返回-1,设置error
二、守护进程创建
守护进程
daemon进程。通常运行于操作系统后台,脱离控制终端。一般不与用户直接交互。周期性的等待某个事件发生或周期性执行某一动作。
不受用户登录注销影响。通常采用以d结尾的命名方式。
创建守护进程,最关键的一步是调用setsid函数创建一个新的Session,并成为Session Leader
守护进程创建步骤:
- fork子进程,让父进程终止
- 子进程调用 setsid() 创建新会话
- 改变工作目录位置 chdir(),防止目录被卸载
- 通常根据需要,重设umask文件权限掩码,影响新文件的创建权限
- 通常根据需要,关闭/重定向文件描述符
- 守护进程 业务逻辑。while()
#include<stdio.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>
#include<pthread.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
pid_t pid;
int ret,fd;
pid = fork();
if (pid > 0) //父进程终止
exit(1);
pid = setsid();//创建会话
if (pid == -1)
{
sys_err("setsid error");
}
ret = chdir("/home/itgan/linux");//改变工作目录位置
if (ret == -1)
{
sys_err("chdir error");
}
umask(0022);//改变文件访问权限掩码
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);
while(1);//模拟守护进程业务
return 0;
}
执行文件后即可在后台发现此进程,使用命令 ps aux 进行查看,该进程不受用户登录、注销的影响,一直运行着,可以使用 kill -9 PID 强制结束
三、线程
进程:有独立的进程地址空间,有独立的pcb, 分配资源的最小单位。
线程:没有独立的进程地址空间,有独立的pcb, 最小的执行单位。
ps -Lf 进程id ---> 线程号LWP -->cpu 执行的最小单位。
ps -Lf 进程号 查看进程的线程
如果一个进程创建了多个线程,那么它就能更快的去争夺CPU,更快的执行
线程共享资源:
1.文件描述符表
2.每种信号的处理方式
3.当前工作目录
4.用户ID和组ID
5.内存地址空间 (.text/.data/.bss/heap/共享库)
线程非共享资源
1.线程id
2.处理器现场和栈指针(内核栈)
3.独立的栈空间(用户空间栈)
4.errno变量
5.信号屏蔽字
6.调度优先级
*三级映射
借助进程机制实现了线程
- 轻量级线程,存在pcb,创建线程使用的底层函数和进程一样,都是clo