嵌入式第九次课堂笔记

今日课堂目标:信号
多线程间通信
信号与信号量并不相同,信号是一种向进程发送通知,告诉其某件事情发生了什么的一种特殊通知机制。发送信号也有多种方法,可以是另一个进程发送信号,内核发送信号,底层硬件发送信号。例如当输入发生段错误时,就会由底层硬件发出SIGSEGV的信号并且终止进程,所以硬件异常也会产生信号。用kill语句加上进程ID可以结束进程。
常用信号有62种,在命令行执行kill -i时,就可以显示所有信号列表。常用信号有:SIGABRT信号是终止进程,并产生core文件,SIGBUS说明硬件故障,会终止进程并且产生core文件,SIGIO是异步通知信号,可以用来终止进程,SIGSEGV说明无效存储访问,也会终止进程并且产生core文件,SIGINT是用来终止进程,类似于Ctrl+c,SIGTERM是终止信号,kill PID时,默认发送的就是这个信号。
所以,当了解完信号作用之后,就可以在编程中发送信号。void abort()是异常退出时调用的,alarm函数相当于一个时钟,语法是:unsigned int alarm(unsigned int seconds);可以输入秒数int raise(int sig)是给本身发送信号,这三个都是对自己发送信号,并且默认终止,所以并不常用。int kill(pid-t pid,int sig)是对别的进程发送信号。
例如:
在这里插入图片描述
这个程序相当于关闭所有进程,所以会重启系统。kill()可以用来送参数sig指定的信号给参数pid指定的进程,参数pid有几种情况:pid>0时将信号传给进程识别码为pid的进程,pid=0时将信号传给和目前进程相同进程组的所有进程,pid=-1时将信号像广播般传递给系统内的所有进程,pid<0时将信号传给进程组识别码为pid绝对值的所有进程。
在这里插入图片描述
调用alarm函数会十秒后产生SIGALRM语句,并且终止进程。若加入while语句,则可以停止十秒,相当于制定了一个闹钟。若加入一个pause函数,会令目前的进程暂停(进入睡眠状态), 直到被信号(signal)所中断.
对于信号处理也有多种方式,可以忽略,也可以执行用户需要执行的动作,也可以是默认处理,但是大部分语句都是终止进程。忽略信号就是当做没有收到这个信号,默认处理就是终止进程。若参数为SIG-IGN时则忽略信号,若参数为SIG-DFL时则默认信号,若要捕获则将参数设置为void(*)(int)的捕获函数的地址,当信号发生时,会自动调用捕获函数来进行相应的处理。捕获函数的int参数,用于接受信号编码。
线程和进程是有区别的。线程是进程内部的调用实体,多个线程是共享进程的空间,进程退出则在进程中的所有线程则退出。所以进程更加健壮,因为当一个进程失败不会影响其他进程。线程的特点有线程切换的开销很低,实际就是函数的切换,并且线程通信机制简单,是使用全局变量。线程创建包括三个参数,第一个参数是线程ID,第二个是线程属性,但是大部分按照系统默认,第三个参数是传参,成功则返回0,失败则返回非0。相较于进程,多线程有天然的共享进程,因此线程数据共享是天然的,所以他的开销更少并且操作更少并且对于线程而言,保护资源就是重点。线程在创建和退出之后,还要学会线程等待。线程状态分为分离状态和可结合状态。
线程的资源保护机制分为互斥锁,线程信息量和条件变量。
互斥锁的使用是先定义一个互斥锁,相当于一个变量,然后对互斥锁进行初始化,并且预设互斥锁的初始值,然后进行加锁解锁,最后在进程退出时销毁互斥锁。但是互斥锁只能在线程中使用,若要在进程中必须使用二级信号量。
线程信号量中提供的信号量都是经过封装的,所以使用起来较方便。首先,先定义信号量集合,例如sem-t sem[3]就是定义三个信号量,然后就是初始化信号量,函数是#include<semaphore.h>
int sem-init(sem-t *sem,int pshared,unsigned int value);
就是初始化线程信号量集合中的某个信号量,给他设置一个初始量,成功则返回0,失败返回-1,errno被设置,但是错误号是不反悔的,而是设置在errno中。第一个参数就是定义过的数组,第二个参数若为0,则是给线程使用,若为非0,则可以给进程使用,第三个参数是初始化值。然后进行p,v操作。p操作的函数是
#include<semaphore.h>
int sem-wait(sem-t *sem);
p操作就是操作集合中某个信号量,值为-1,如果不能成功则一直阻塞到p操作成功为止。并且成功则返回0,不成功返回-1。v操作就是S=S+1,若S>0则执行V操作的进程继续执行;若S<0,则从阻塞状态唤醒一个进程,并将其插入就绪队列,执行V操作的进程继续执行。最后再进程结束时,删除线程信号量集合。
其次,还可以多线程配合工作,当线程检测到某条件不满足时就休眠,直到别的线程条件准备好,然后通过条件变量将其唤醒。
最后,还可以使用条件变量就是线程间的协同,就是主线程对va变量循环+1,次线程发现va==5时,打印va的值并且将va清0,如果va的值不为5就什么都不做。条件变量的使用步骤是:先定义一个条换变量由于条件变量需要互斥锁的配合,所以还需要定义一个线程互斥锁,函数是#include<pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);第一个参数是定义好的条件变量的地址,第二个是条件变量的属性,若成功则返回0,失败则返回非0。然后使用条件变量,函数是#include<pthread.h>
int pthread_cond_wait(pthread_cond_t *resrict cond,pthread_mutex_t *restrict mutex);就是检测条件变量cond,如果cond没有被设置,表示条件还不满足,别人还没有对cond进行设置,此时pthread_cond_wait会休眠阻塞,直到别的线程设置cond表示条件准备好后,才会被唤醒。同样成功则返回0,失败返回非零错误号。唤醒的函数是int pthread_cond_signal(pthread_cond_t *cond);当检测到cond被设置时就不再休眠,线程继续进行,并且使用别的线程准备好的数据来做事。最后太删除条件变量,并且也删除互斥锁。
对于线程和进程是有区别的,进程是资源分配的最小单位,线程是任务调度的最小单位;每个进程拥有独立的地址空间,多个进程共享进程地址空间。在需要频繁创建和销毁时,需要大量计算时使用线程。高性能交易服务器中间件主张多进程,强相关的处理要用线程,弱相关的处理用进程,多机分布的用进程,多核分布的用线程。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值