俄罗斯方块的例子 同步 异步:事件不知道什么时候到来。到来后的结果不知道。 异步事件的处理:查询法, 通知法。 江边钓鱼的例子,是每次用渔网自己捞还是看鱼漂的通知。异步事件发生稀疏,发生频率高查询法,养殖场放鱼。火灾事件,传感器。 a date,看手表 定闹钟。过马路,红绿灯。主动与被动。
一、信号
1. 信号的概念
信号是软件中断。 信号的响应依赖于中断。两者的关系。 时间片轮转。调度策略。 中断,硬件的角度。
2. signal();
原型
给一个信号定义新的行为sighandler_t,是否保存旧的行为 返回值。c语言 名空间管理不善。typedef其实没有实现。sighandler_t目前自己抽象出来的。1. 命令kill -l 查看信号,编号1-31 叫做标准信号,之后sigrtmin-sigrtmax 34-64实时信号。core文件。2. ulimit -a core file size ulimit -c 10240 3. void(*signal(int signum, void (*func)(int)))(int)防止了名空间冲突。; 4. 信号会打断阻塞的系统调用。
3. 信号的不可靠
以start.c为例,标准信号丢失是一定的。这里说的是信号的行为不可靠。没有人为调用行为。内核帮你布置。
4. 可重入函数
- 为了解决信号的不可靠。第一次调用还没有结束第二次调用就开始了 重入,像递归不是递归。信号的执行现场由内核来布置。 所有的系统调用都是可重入的。 反过来不成立。一部分库函数也是可重入的,如:
memcpy给定源和目的 是不冲突的 rand不可重入,rand_r (reintable 待查)重入。尤其是返回值为指针的。localtime_r版本,这个指针所指向的结构体 在静态区上,另外的版本可以用到信号处理当中。
5.信号的响应过程
- 信号从收到到响应有一个不可避免的延迟。(是因为有中断把当前执行过程打断,压内核即将往外走时才会看到信号 kernel即将回到user态的路上响应的,岔路 打电话)
- 思考:如何忽略掉一个信号的?signal函数 ign 实际上把指定的mask位置为0.不能阻止信号的到来,但可以决定信号是否被响应以及在什么时候被响应。 标准信号为什么要丢失? 标准信号的响应没有严格的顺序。
6. 信号相关的常用函数
- kill();发信号给某个进程(某组)/检测某个进程是否存在
- raise();
- alarm();
- setitimer();//精度控制更好 例:使用单一计时器,利用alarm或setitimer构造一组函数,实现任意数量的计时器. 有了时间观念,机器可以做更多的事情了2. pause(); 3. abort(); 4. system(); 5. sleep(); nanosleep usleep select
7. 信号集
信号集类型:sigset_t 即type sigemptyset(); sigfillset(); sigaddset(); sigdelset(); sigismember();
8. 信号屏蔽字/信号pending集的处理
sigprocmask(); 人为方式控制干扰mask 当前信号状态,mask;信号的到来不知道,信号响应依赖于中断。不能决定信号什么时候到来,能决定信号什么时候被响应。
9. 扩展
- sigsuspend(); //wait for signal pause()
- sigaction(); →signal();
- setitimer();
- 实时信号 标准信号两个特点:会丢失,位图来进行记录的;响应没有严格的顺序要求,未定义行为,非随机。 为了解决标准信号的不足。 如果一个进程中既收到标准信号又收到实时信号先响应标准信号
二、多线程
1. 线程的概念
一个正在运行的函数。多线程同一个地址空间内。虚拟地址空间。通信,全局变量都能看到。线程间通信。兄弟关系。从并发角度看 先标准化再实现函数 故比多进程并发更简单。库函数支持线程并发。
posix线程是一套标准而不是实现。
openmp线程。
线程标识:pthread_t posix下的线程标识,类型?都可。具体的类型不知道,指针 整形 结构体,不要贸然打印%d.linux环境下整形数。ps axf进程关系 。ps axmmore?- -表示线程,容器的概念。会话容器承载进程组,进程组容器 承载进程。进程 容器 承载线程。处理器以线程为单位调度。ps ax -L以linux格式?
**pthread_equal()**比较两个线程id是否相同。
编译链接的时候需要-pthread.
**pthread_self();**相当于getpid
2. 线程的创建
涉及到的函数: pthred_create() 线程的调度取决于调度器策略 线程的终止: 3种方式:1. 线程从启动例程返回,返回值就是线程的退出码。2. 线程可以被同一进程中的其他线程取消。3. 线程调用pthread_exit()函数 pthread_join ⇒ wait()原语 收尸包括 栈的清理: pthread_cleanup_push() ;pthread_cleanup_pop();类似挂钩子函数at_exit,但是钩子函数不可以改变 没有主动权,但是这两个操作. pop从钩子函数中取内容。 线程的取消选项 先取消 再收尸。pthread_cancel(); 取消有两种状态:允许和不允许(信号来了不响应) 允许取消又分为:异步cancel和推迟cancel(默认)→推迟到cancel点再响应。 cancel点:POSIX定义的cancel点,都是可能引发阻塞的系统调用 pthread_setcancelstate():设置是否允许取消 pthread_setcanceltype():设置取消方式 pthread_testcancel():本函数什么都不做,就是一个取消点。 线程分离 pthread_detach(pthread_t thread);不再管它了
3. 线程同步
- 互斥量:
- pthread_mutex_t
- 相关函数:
pthread_mutex_init pthread_mutex_destroypthread_mutex_lock静态初始化 使用宏;动态初始化,使用函数
- pthread_mutex_trylock();
- pthread_mutex_unlock();
- pthread_once(); todo
- 条件变量 (通知法): pthread_cond_t pthread_cond_init(); 同样两种初始化方式,静态加动态 pthread_cond_destroy(); pthread_cond_broadcast(); 打断wait pthread_cond_signal();
- 信号量:
- 读写锁:读锁→共享锁 写锁→互斥锁 避免写锁饥饿 。
4.线程相关的属性;
pthread_atrr_init() ulimit -a查看栈大小
pthread_attr_destroy();
pthread_attr_setstacksize();
见 man pthread_attr_init的see also
线程同步的属性
互斥量属性: 初始化和销毁
pthread_mutexatrr_init();
pthread_mutexattr_destroy();
pthread_mutexattr_getpshared(); p:persistent 跨进程起作用
pthread_mutexattr_setpshared();
clone(); flags选项中选择资源都分离,那么创建出进程;若是共用(fd table,parent process…),那么创建出兄弟,线程。介于多进程与多线程之间,有一些资源共用,有一些资源独立。即不是子进程也不是线程,来满足开发的需要。
pthread_mutexattr_gettype();
pthread_mutexattr_settype();
条件变量属性:
pthread_condatrr_init/destroy
读写锁属性
5. 可重入的概念;
多线程中的IO 线程与信号 pthread_sigmask(); sigwait(); pthread_kill(); 线程与fork 不同线程原语对fork产生结果不同,一个进程有多个线程,fork的时候是所有线程都复制还是只复制一个线程
6. openmp
非函数级别,非语言的角度。 使用中间层,借助编译器,提供语法标识让编译器识别 编译器的要求 >gcc4.0 跨语言并发标准
- 线程三种常见工作模式
- 流水线
- 一个大任务分成若干子任务,最后汇总
- C/S 客户端/服务器