会话
创建会话
创建一个会话需要注意以下6点注意事项
- 调用进程不能是进程组组长,该进程变成新会话首进程
- 该进程成为一个新进程组的组长进程
- 需要root权限(nbuntu不需要)
- 新会话丢弃原有的控制终端,该会话没有控制终端
- 该调用进程是组长进程,则出错返回
- 建立新会话时,先调用fork,父进程终止,子进程调用setsid
getsid 函数
获取进程所属的会话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 函数的进程,既是新的会长,也是新的组长。
练习: fork 一个子进程,并使其创建一个新会话。查看进程组 ID、会话 ID 前后变化
#include<stdlib.h>
#include<unistd.h>int main(void)
{pid_t pid;if((pid = fork()< 0)){perror("fork");exit(1);}else if(pid == 0){ printf("child process PID is %d\n",getpid());printf("Group ID of child is %d\n",getpgid(0));printf("Session ID of child is %d\n",getsid(0));sleep(10);setsid(); //子进程非组长进程,故其成为新会话首进程,且成为组长进程。该进
程id即为会话进程printf("Changed:\n");printf("child process PID is %d\n",getpid());printf("Group ID of child is %d\n",getpgid(0));printf("Session ID of child is %d\n",getsid(0));sleep(20);exit(0); } return 0;
}
结果:
守护进程
- Daemon(精灵)进程,是 Linux 中的后台服务进程,通常独立于控制终端并且周期性地执行某种任务或等待处理 某些发生的事件。一般采用以 d 结尾的名字。
- Linux 后台的一些系统服务进程,没有控制终端,不能直接和用户交互。不受用户登录、注销的影响,一直在运行着,他们都是守护进程。如:预读入缓输出机制的实现;ftp 服务器;nfs 服务器等。
- 创建守护进程,最关键的一步是调用 setsid 函数创建一个新的 Session,并成为 SessionLeader。
创建守护进程
-
创建子进程,父进程退出
所有工作在子进程中进行形式上脱离了控制终端 -
在子进程中创建新会话
setsid()函数
使子进程完全独立出来,脱离控制 -
改变当前目录为根目录
chdir()函数
防止占用可卸载的文件系统
也可以换成其它路径 -
重设(指定)文件权限掩码
umask()函数
防止继承的文件创建屏蔽字拒绝某些权限
增加守护进程灵活性 -
将0/1/2重定向/dev/null dup2()关闭文件描述符
继承的打开文件不会用到,浪费系统资源,无法卸载 -
开始执行守护进程核心工作
-
守护进程退出处理程序模型
#include<stdio.h>#include<unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h> void mydaemond(void){pid_t pid,sid;int ret;pid = fork();if(pid > 0){ //父进程退出return 0;} //创建会话sid = setsid();ret = chdir("/home/itcast/"); if( ret == -1 ){perror("chdir error");exit(1);} umask(0022);close(STDOUT_FILENO);open("/dev/null",O_RDWR);dup2(0,STDOUT_FILENO);dup2(0,STDERR_FILENO);}int main(void){mydaemond();while(1){}return 0;}