一、进程间通信
1、信号:是一种向进程发送通知,告诉其某件事情发生了的一种简单通信机制。
(1)信号的产生
1)另一个进程发送信号;
2)内核发送信号;
3)底层硬件发送信号。
例1:
例2:
(2)信号列表
常用信号:
信号宏名 信号编号 说明 系统默认处理方式
SIGABRT 6 终止进程,调abort函数时产生 终止,产生core文件
SIGALRM 14 超时,调用alarm函数时产生 终止
SIGBUS 7 硬件故障 终止,产生core文件
SIGCHLD 17 子进程状态改变 忽略
SIGINT 2 终止进程(ctrl+c) 终止
SIGIO 29 异步通知信号 终止
SIGKILL 9 无条件终止进程,不可被捕获或忽略 终止
SIGPIPE 13 写没有读权限的管道文件时 终止
SIGPOLL 8 轮询事件,涉及POLL机制 终止
SIGQUIT 3 终止进程(ctrl+\) 终止,产生core文件
SIGSEGV 11 无效存储访问(指针错误) 终止,产生core文件
SIGTERM 15 终止,kill PID时,默认发送该信号 终止
SIGUSR1 10 用户自定义信号1 终止
SIGUSR2 12 用户自定义信号2 终止
(3)信号发送
1)int kill(pid_t pid,int sig);
例1:
2)int raise(int sig);
3)unsigned int alarm(unsigned int seconds);
例1:
例2:
4)void abort();
(4)进程挂起pause
例1:
(5)信号处理的方式
1)忽略;
2)执行用户需要执行的动作(捕获);
3)默认处理。
(6)信号处理API:typedef void (*sighhandler_t)(int);
例1:(10s后没反应,被忽略)
例2:
例3:(ctrl+c或等待10s都可打印并退出)
例4:
例5:
二、线程
1、线程是任务调度和执行的基本单位
2、线程存在的原因
(1)进程实现多任务的缺点
1)进程间切换的计算机资源开销大,切换效率非常低;
2)进程间数据共享的开销很大。
(2)线程和进程的关系
1)线程是进程的一个执行单元,是进程内的调度实体,比进程更小的独立运行的基本单位,线程也被称为轻量级进程;
2)同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间;
3)进程退出,进程中所有线程全部退出;
4)一个进程崩溃后,不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉,所以多进程要比多线程健壮;
5)线程不可能完全替代进程;
6)线程拥有独立的属性。
3、线程拥有的独立属性
(1)每个线程拥有自己独立的线程ID(TID);
(2)每个线程有独立的切换状态;
(3)调度优先级;
(4)有自己独立的函数栈;
(5)自己独立的错误号;
(6)每一个线程有自己独立的信号屏蔽字和未决信号集;
(7)每个线程有自己独立的tack_struct结构体。
4、线程特点
(1)线程切换的开销很低(实质是函数的切换);
(2)线程通信机制简单(全局变量)。
5、线程操作
(1)线程函数的提供
1)非os,而是线程库libpthread.a/.so;
2)线程控制函数有:pthread_create、pthread_join、pthread_detach、pthread_cancel、pthread_exit等。
(2)线程创建
1)int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
(3)线程退出
1)被动退出:int pthread_cancel(pthread_t thread);
2)主动退出:
void pthread_exit(void *retval);
return返回
3)注册线程退出处理函数:
void pthread_cleanup_push(void (*routine)(void *),void *arg);
void pthread_cleanup_pop(int execute);
(4)线程等待
(5)线程状态
6、线程同步
(1)线程与进程区别
1)进程:进程空间天然是独立的,因此进程间资源的保护是天然的(现成的),需要重点关心进程间的通信;
2)线程:多线程天然地共享进程空间,因此线程数据共享是天然的(现成的),需要重点关心资源的保护。
(2)线程资源保护机制
1)互斥锁使用步骤
定义一个互斥锁(变量):pthread_mutex_t mutex;;
初始化互斥锁:
预设互斥锁的初始值:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER编译时初始化锁位解锁状态;
加锁解锁;
进程退出时销毁互斥锁。
2)线程信号量使用步骤
定义信号量集合;
初始化集合中的每个信号量;
p、v操作;
进程结束时,删除线程信号量集合。
3)条件变量使用步骤
定义一个条件变量(全局变量)由于条件变量需要互斥锁的配合,所以还需要定义一个线程互斥锁(pthread_cond_t);
初始化条件变量;
使用条件变量;
删除条件变量,也需要把互斥锁删除。
例1:
例2:(休眠1s)
例3:(休眠2s)
例4:
例5:
例6:
例7:
7、进程与线程
(1)多线程比多进程成本低,但性能更低
1)多进程是立体交通系统,虽然造价高,上坡下坡多耗点油,但是不堵车;
2)多线程是平面交通系统,造价低,但红绿灯太多,老堵车。
(2)区别
1)进程是资源分配的最小单位,线程是任务调度的最小单位;
2)每个进程拥有独立的地址空间,多个线程共享进程地址空间:
线程之间切换比进程之间切换开销少;
线程的调度必须通过频繁加锁来保持同步,影响了线程并发性能;
进程比线程更健壮,多进程之间相互独立,进程的异常对其他进程无影响,一个线程的崩溃可能影响其他线程或者整个程序;
线程之间的通信更方便(小数据量),同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行,不过如何处理好同步与互斥是编写多线程程序的难点;
多线程的代码结构比多进程代码结构易读。
(3)进行选择
1)需要频繁创建销毁的优先用线程;
2)高性能交易服务器中间件,如TUXEDO,都是主张多进程的;
3)需要进行大量计算的优先使用线程;
4)强相关的处理用线程,若相关的处理用进程;
5)多机分布的用进程,多核分布的用线程。