维系一个会话,最常见的有两种方式:
一是基于某种凭证,比如web网站的登录会话,在登录验证之后,服务器就会返回一个session id作为凭证。用户之后的请求总是会带上这个id,而服务器通过这个id也就能知道用户是谁。直到用户注销登录、或者登录超时,服务器会清洗掉对应的session id,这个id就失效了,会话也就随之而结束。
第二种方式是基于连接的,当用户和系统之间的连接启用时,系统会对用户进行验证,验证通过之后,来自这个连接的操作都是属于这个用户的。直到连接断开,则会话结束。
linux系统的会话就是以第二种方式来维系的。会话基于连接,那么连接的安全性就决定了会话的安全性。以最常见的两种连接为例:
1、本地连接,用户是直接通过键盘显示器来跟系统交互的,键盘显示器直接连接在主机上,连接被篡改基本上是不可能的;
2、远程连接,以ssh为例,其协议会进行加密,从而避免连接被篡改;
调用以下函数可以使进程成为会话组长:
pid_t setsid(void)
要注意的是:
1.调用进程不能是进程组组长,该进程变成新会话首进程(session header)
2.该进程成为一个新进程组的组长进程。
3.需有root权限(ubuntu不需要)
4.新会话丢弃原有的控制终端,该会话没有控制终端
5.该调用进程是组长进程,则出错返回
6.建立新会话时,先调用fork, 父进程终止,子进程调用
#include <stdio.h> #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 ", getpid()); printf("Group ID of child is %d ", getpgid(0)); printf("Session ID of child is %d ", getsid(0)); sleep(10); setsid(); // 子进程非组长进程,故其成为新会话首进程,且成为组长进程。该进程组id即为会话进程 printf("Changed: "); printf("child process PID is %d ", getpid()); printf("Group ID of child is %d ", getpgid(0)); printf("Session ID of child is %d ", getsid(0)); sleep(20); exit(0); } return 0; } 输出结果: child process PID is 3978 Group ID of child is 3977 Session ID of child is 3305 Changed: child process PID is 3978 Group ID of child is 3978 Session ID of child is 3978
通过以下函数查看会话进程ID
pid_t getsid(pid_t pid)
pid为0表示察看当前进程session ID
注:组长进程不能成为新会话首进程,新会话首进程必定会成为组长进程。