多线程应用程序设计
>> 概述
一、使用多线程的理由
1、和进程相比,它是一种“节俭”的多任务方式。
在Linux系统中,启动一个新的进程必须分配独立的地址空间,建立众多的数据库来维护它的代码段、堆栈段和数据段。
而运行一个进程的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据。
因此,线程间切换的时间远小于进程间切换所需要的时间。
2、线程间方便的通信机制
不同进程具有独立的数据空间,要进行数据的传递只能通过通信的方式;
同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其他线程所用。
二、多线程的优点
1、提高应用程序的响应。
2、使多CPU系统更加有效。
3、改善程序结构。
>>多线程的编程
一、编写Linux下的多线程,需要使用头文件pthread.h,连接时需要使用库libpthread.a(/usr/lib)
1、线程标识符pthread_t
typedef unsigned long int pthread_t;
用来标识一个线程。
2、线程创建函数pthread_create
第一个参数为指向线程标识符的指针
第二个参数用来设置线程属性NULL表示默认属性
第三个参数是线程运行函数的起始地址
第四个参数是运行函数的参数NULL
函数返回值是个int,创建线程成功,返回值0,新创建的线程则运行参数三、四确定的函数。
3、用来等待一个线程的结束pthread_join
第一个参数为被等待的线程标识符
第二个参数为一个用户定义的指针,用来存储被等待线程的返回值。
该函数是线程阻塞的函数,调用它的函数将一直等待到被等待线程的结束,当返回时,被等待线程的资源被收回。
4、线程结束函数pthread_exit
参数是函数的返回代码。
注意:一个线程不能被多个线程等待。
二、线程的属性
属性值不能直接设置,须使用相关函数操作:
pthread_attr_init需在线程函数创建之前调用
三、线程的优先级
是线程的常用的属性,
用pthread_attr_getschedparam
和pthread_attr_setschedparam
来进行存放、设置。
四、互斥锁
用来保证一段时间内只有一个线程在执行一段代码。
声明互斥变量pthread_mutex_t
函数pthread_mutex_init用来生成一个互斥锁
pthread_mutex_lock用来加锁
pthread_mutex_unlock用来解锁
五、条件变量
互斥锁只有两种状态:锁定和非锁定。
条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补互斥锁的不足。
使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程通常解开相应的互斥锁并等待条件发生变化,一旦其他的线程改变了条件变量,相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程,这些线程将重新锁定互斥锁并重新测试条件是否满足。
pthread_cond_init返回值int,参数两个:
第一个是一个指向条件变量的指针
第二个是一个指向条件变量属性结构体的指针
pthread_cond_t条件变量的结构体
pthread_condattr_t是一个条件变量属性的结构体
注意:条件变量只有未被使用时才能重新初始化或被释放。
pthread_cond_destroy释放一个条件变量的函数,参数就为被释放的条件变量
pthread_cond_wait函数;使线程阻塞在一个条件变量上。返回值是int,参数二个:
第一个指向条件变量的指针
第二个指向互斥锁变量的指针。
pthread_cond_timedwait也可用来阻塞线程。
比上一个函数多了一个时间参数,也就是说经历了时间参数后,即使条件变量不满足,阻塞也被解除。
pthread_cond_signal用来释放被阻塞在条件变量上的一个线程。
返回值是int,参数为指向条件变量的指针。
多个线程阻塞在此条件变量上时,哪一个线程被唤醒是由线程的调度策略所决定的。
例:著名的生产者-消费者问题
主程序中分别启动生产者线程和消费者线程,生产者线程不断顺序地将0到1000的数字写入到共享的循环缓冲区,同时消费者线程不断地从共享的循环缓冲区读取数据。
也即保证多线程,同时保证同一时刻只能有一个线程读写共享区。
>>串行端口程序设计
一、预备知识
1、串口简介
常见的通信方式分为并行通信和串行通信。
并行通信是指多条数据传输线将一个文件的各位同时传送,特点是传输速度快,适用于短距离通信,但要求传输速度较高的应用场合。
串行通信是指利用一条传输线将文件一位一位的顺序传送。特点是通信线路简单,利用简单的线缆就可实现通信,降低成本,适用于远距离通信,但传输速度慢的应用场合。
常用的串口有RS-232-C接口,它是1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的串行通信的标准,全称:数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准。该标准规定采用了一个DB25芯引脚的连接器或9芯引脚的连接线,其中9芯引脚的连接器如下:
2、串口文件
串口一/dev/ttyS0
串口二/dev/ttyS1
执行若出现:/dev/ttyS0:No such file or directory
Cd /dev |ls
ln –s /dev/tts/0 /dev/ttyS0
二、串口应用开发
1、头文件
Include <fcntl.h>//文件控制定义
Include <termios.h>//终端控制定义
Include <errno.h>//错误号定义
2、打开串口
int fd;
fd=open(“/dev/ttyS0”,O_RDWR);
if (fd==-1)
perror(“提示错误”);
3、关闭串口
close(fd);
4、应用程序往串口(终端)写数据(发送)
Char buffer[1024];
Int length=1024;
Int nbyte;
nbyte=write(fd,buffer,length);
5、应用程序读取串口(终端)数据(接收)
Char buffer[1024];
Int length=1024;
Int readbyte=read(fd,buffer,length);
6、串口属性设置
包括波特率(115200)、效验位(无)、停止位(1)
/arm2410s/kernl-2410s/include/asm/termios.h
struct termio
{
unsigned short c_iflag; /*输入模式标志 */
unsigned short c_oflag; /*输出模式标志 */
unsigned short c_cflag; /*控制模式标志 */
unsigned short c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[NCC]; /* control characters */
};
(1) 波特率设置
struct termios opt;
tcgetattr(fd,&opt);
cfsetispeed($opt,B19200);
tcsetattr(fd,TCSANOW,&opt);
(2) 检验位:无,数据位8
Opt.c_cflag&=~PARENB
Opt.c_cflag&=~CSTOPB
Opt.c_cflag&=~CSIZE
Opt.c_cflag|=~CS8
(3) 设置停止位(1)
Opt.c_cflag&=-CSTOPB