进程和线程
Posted 木子牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了进程和线程相关的知识,希望对你有一定的参考价值。
程序和进程:
程序是存放在磁盘上的处于某个目录中的一个可执行文件。
进程和进程ID:
程序的执行实例被称为进程,操作系统确保每个进程都有一个唯一的数字标识符,称为进程ID,而且确保为非负数。
进程控制:
有个主要进程控制的主要函数:fork,exec,waitpid
#C
#include apue.h
#include <sys/wait.h>
int main (void) {
char buf(MAXLINE)
pid_t pid;
int status;
if((pid = fork) < 0) {//创建进程失败
}else if (pid == 0) {
//子进程执行代码
} else {//父进程代码
if((pid = waitpid(pid,&status,0)) < 0) {
err_sys("waitpid error");
}
}
}
线程和线程ID:
通常一个进程只有一个线程控制线程,同一时刻只执行一组机器指令,对于某些问题,如果不同部分各使用一个控制线程,那么整个问题解决起来就容易的多,在一个进程的内的所有线程共享同一地址空间,文件描述,栈以及进程相关的属性,线程也用ID标示,但是线程ID只在进程内部起作用。控制线程的函数和进程的函数相似但是另有一套,在进程模型建立很久之后,线程模型才引入到uninx系统。两个模型之间有相互作用。
进程控制:
进程的终止:
正常终止:exit,die,
接到一个信号终止
线程崩溃终止
除了进程ID,进程也有一些其他标识符,
getpid 获得进程ID
getppid 获得进程的父ID,(每一个进程都有一个唯一父进程)
getuid 进程的实际用户ID
fork:创建子进程。fork调用一次返回两次,
父进程时返回 子进程的ID,子进程时返回0;
子进程是父进程的副本,复制父进程的数据空间,堆栈,但不共享父进程的数据。
一般来说在fork之后父进程执行还是子进程执行是不确定的。因为进程的执行是系统调度的。
关于文件的共享,如果想使文件数据统一,可以在父进程等待子进程执行完毕后,父进程在执行相关操作。
fork一般用在:
1:一个父进程希望复制自己,是父,子进程同时执行不同的代码段。这在网络服务进程是常见的:父进程接受请求,子进程处理请求
2:一个进程要执行不同的程序。
wait和waitpid:
当一个进程正常或是异常终止时,内核就向其父进程发送SIGCHLD信号。因为子进程终止是个异步事件,所以这种信号也是内核异步通知父进程。父进程可以选择负略此信号或是提供一个该信号发生时处理的回调函数来处理。对于这种信号,系统默认的操作是负略它。调用wait,waitpid获取子进程终止状态时可能发生的事情:
1:如果所有子进程都在运行则阻塞
2:如果一个子进程已经终止,正在等待父进程获取终止状态,则取得该子进程的终止状态立即返回。
3:如果没有任何子进程则立即出错返回。
如果在任意时刻调用wait可能会造成阻塞。
一般在父进程使用的函数:
pcntl_wait — 等待或返回fork的子进程状态
pcntl_waitpid — 等待或返回fork的子进程状态
pcntl_wexitstatus — 返回一个中断的子进程的返回代码
pcntl_wifexited — 检查状态代码是否代表一个正常的退出。
pcntl_wifsignaled — 检查子进程状态码是否代表由于某个信号而中断
pcntl_wifstopped — 检查子进程当前是否已经停止
pcntl_wstopsig — 返回导致子进程停止的信号
pcntl_wtermsig — 返回导致子进程中断的信号
在父进程和子进程都能使用的:
pcntl_alarm — 为进程设置一个alarm闹钟信号
pcntl_exec — 在当前进程空间执行指定程序
pcntl_fork — 在当前进程当前位置产生分支(子进程)。译注:fork是创建了一个子进程,父进程和子进程 都从fork的位置开始向下继续执行,不同的是父进程执行过程中,得到的fork返回值为子进程 号,而子进程得到的是0。
僵尸进程:没有被父进程回收(wait)的子进程会变成僵尸进程(系统资源得不到释放);
孤儿进程:父进程先于子进程结束,子进程会成为孤儿进程被(init托管)。
进程组:N个进程的集合。通常进程组与同一作业相关联,可以接受来自同一终端的各种信号。
每个进程组都有一个进程组ID,一般于组长进程相同,组长进程退出,并不改变进组ID。
会话:会话是一个或多个进程组的集合,终端连接服务器会开启一个终端会话,关闭终端,会话的进程会全部kill。
孤儿进程会使用setsid开启一个新的会话,以独立于会话终端
信号:
信号本质:
信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。
信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。信号机制经过POSIX实时扩展后,功能更加强大,除了基本通知功能外,还可以传递附加信息。
信号来源
信号事件的发生有两个来源:硬件来源(比如我们按下了键盘或者其它硬件故障);软件来源,最常用发送信号的系统函数是kill, raise, alarm和setitimer以及sigqueue函数,软件来源还包括一些非法运算等操作。
信号是程序中断的标识。
信号是软件中断:每一个信号都有一个名字,这些都是三个字符开头的SIG。
很多条件可以产生信号:用户按键引起的中断,比如用户按下delete键。
信号是异步事件的经典实例。产生信号的事件对于进程而言是随机出现的。
处理信号的方法
1:忽略此信号,但是SIGKILL和SIGSTOP信号不能忽略这是超级用户终止进程的产生的信号
2:定义一个信号回调函数告诉系统出现此信号时的处理。信号处理函数可以使用waitpid,来获得进程ID,终止状态。
3:执行系统默认操作。
当一个进程调用fork时,其子进程继承父进程的信号处理方式。
信号处理函数:
pcntl_signal_dispatch — 调用等待信号的处理器
pcntl_signal — 安装一个信号处理器
pcntl_sigprocmask — 设置或检索阻塞信号
pcntl_sigtimedwait — 带超时机制的信号等待
pcntl_sigwaitinfo — 等待信号
编号 信号名称 缺省动作 说明
1 SIGHUP 终止 终止控制终端或进程
2 SIGINT 终止 键盘产生的中断(Ctrl-C)
3 SIGQUIT dump 键盘产生的退出
4 SIGILL dump 非法指令
5 SIGTRAP dump debug中断
6 SIGABRT/SIGIOT dump 异常中止
7 SIGBUS/SIGEMT dump 总线异常/EMT指令
8 SIGFPE dump 浮点运算溢出
9 SIGKILL 终止 强制进程终止
10 SIGUSR1 终止 用户信号,进程可自定义用途
11 SIGSEGV dump 非法内存地址引用
12 SIGUSR2 终止 用户信号,进程可自定义用途
13 SIGPIPE 终止 向某个没有读取的管道中写入数据
14 SIGALRM 终止 时钟中断(闹钟)
15 SIGTERM 终止 进程终止
16 SIGSTKFLT 终止 协处理器栈错误
17 SIGCHLD 忽略 子进程退出或中断
18 SIGCONT 继续 如进程停止状态则开始运行
19 SIGSTOP 停止 停止进程运行
20 SIGSTP 停止 键盘产生的停止
21 SIGTTIN 停止 后台进程请求输入
22 SIGTTOU 停止 后台进程请求输出
23 SIGURG 忽略 socket发生紧急情况
24 SIGXCPU dump CPU时间限制被打破
25 SIGXFSZ dump 文件大小限制被打破
26 SIGVTALRM 终止 虚拟定时时钟
27 SIGPROF 终止 profile timer clock
28 SIGWINCH 忽略 窗口尺寸调整
29 SIGIO/SIGPOLL 终止 I/O可用
30 SIGPWR 终止 电源异常
31 SIGSYS/SYSUNUSED dump 系统调用异常
以上是关于进程和线程的主要内容,如果未能解决你的问题,请参考以下文章