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