1、前言
1.1、多进程实现同时读取键盘和鼠标。
观察一个编程实例:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(void)
{
//思路就是创建子进程,然后父子进程中分别进行读键盘和鼠标的工作
int ret = -1;
int fd = -1;
char buf[100];
ret = fork(); //创建子进程
if (ret == 0)
{
//子进程
//读鼠标
fd = open("/dev/input/mouse0", O_RDONLY); //打开鼠标文件
if (fd < 0)
{
perror("open");
return -1;
}
while(1)
{
memset(buf, 0, sizeof(buf));
printf("鼠标读before.\n");
ret = read(fd, buf, 5);
printf("鼠标读出的内容是:[%s].\n", buf);
}
}
else if (ret > 0)
{
//父进程
while(1)
{
memset(buf, 0, sizeof(buf));
printf("键盘读before.\n");
ret = read(0, buf, 5);
printf("键盘读出的内容是:[%s].\n", buf);
}
}
else
{
//子进程创建错误
perror("fork:");
}
return 0;
}
1.2、使用多进程的技术优势
(1)CPU时分复用,单核心CPU可以实现宏观上的并行
(2)实现多任务系统需求(多任务的需求是客观的)
1.3、进程技术的劣势
(1)进程间切换开销大
(2)进程间通信麻烦而且效率低
1.4、解决进程技术的劣势的方案就是线程技术
(1)线程技术保留了进程技术实现多任务的特性。
(2)线程的改进就是在线程间切换和线程间通信上提升了效率。
(3)多线程在多核心CPU上面更有优势。
2、线程的引入
2.1、使用线程技术同时读取键盘和鼠标
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
char buf[100];
//线程函数 次任务
void *func(void *arg)
{
while(1)
{
memset(buf, 0, sizeof(buf));
printf("键盘读before.\n");
read(0, buf, 5);
printf("键盘读出的内容是:[%s].\n", buf);
}
}
int main(void)
{
//思路就是在进程主线程中创建子线程任务,然后在主线程和子线程中分别进行读键盘和鼠标的工作
int ret = -1;
int fd = -1;
pthread_t th = -1;
//gcc 时:注意要用gcc 3.7.2.c -lpehread , -l表示链接,pehread为动态库
//或者使用 gcc 3.7.2.c -pehread
//gcc 3.7.2.c -lpehread 即链接到pthread动态库
ret = pthread_create(&th, NULL, func, NULL); //创建子线程
if (ret != 0)
{
printf("pehread_create error.\n");
return -1;
}
//主任务
//读鼠标
fd = open("/dev/input/mouse0", O_RDONLY);
if (fd < 0)
{
perror("open");
return -1;
}
while(1)
{
memset(buf, 0, sizeof(buf));
printf("鼠标读before.\n");
read(fd, buf, 5);
printf("鼠标读出的内容是:[%s].\n", buf);
}
return 0;
}
2.2、linux中的线程简介
(1)一种轻量级进程
(2)线程是参与内核调度的最小单元
(3)一个进程中可以有多个线程
2.3、线程技术的优势
(1)像进程一样可以被OS调度
(2)同一进程的多个线程之间很容易高效率通信
(3)在多核心CPU(对称多处理器架构SMP)架构下效率最大化。
3、线程常见函数
3.1、线程创建与回收
(1)pthread_create 主线程用来创建子线程
(2)pthread_join 主线程用来等待(阻塞)回收子线程
(3)pthread_detach 主线程用来分离子线程,分离后主线程不必再去回收子线程
3.2、线程取消
(1)pthread_cancel 一般都是主线程调用该函数去消化(让它赶紧死)子线程
(2)pthread_setcancelstate 子线程设置自己是否允许被消化
(3)pthread_setcanceltype
3.3、线程函数退出相关
(1)pthread_exit与return 退出
(2)pthread_cleanup_push
(3)pthread_cleanup_pop
3.4、获取线程id : pthread_self