linux thread hodgepodge == linux application programming 6

Brother Dong's practice diary 2022-08-06 14:04:20 阅读数:870

linuxthreadhodgepodgelinuxapplication

一、再论进程–资源分配的最小单位

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#define NAME "/dev/input/mouse1"
int main()
{

// 思路为,创建子进程,Then read the keyboard separately(父亲)和鼠标(儿子)工作
int ret=-1;int fd=-1;char buf[200];
ret=fork();
if(ret==0){
//child
fd=open(NAME,O_RDONLY);
if(fd<0)
return -1;
while(1){

memset(buf,0,sizeof(buf));//Pockets are emptied for backup data
printf("before read.\n");
read(fd,buf,50);
printf("读出鼠标的内容是:[%s].\n",buf);
}
}
else if(ret>0){
//parent
while(1){

memset(buf,0,sizeof(buf));
printf("before read.\n");
read(0,buf,5);
printf("读出键盘的内容是:[%s].\n",buf);
}
}
else
perror("fork");return 0;
}

2、使用进程技术的优势

  • (1)CPU 分时复用,单核心 CPU It can achieve macro-level multi-task parallelism.

3、Disadvantages of using process technology

  • (1)进程间切换开销大.
  • (2)进程间通信(IPC)麻烦且效率低下.

4、解决方案——线程技术

  • (1)Threading technology retains the characteristics of multitasking processes.
  • (2)The improvement of threads is to improve the efficiency of switching between threads and communication,Inherit the advantages of the process,Overcome the process 的缺点.
  • (3)Multilinear in many CPU The core is more dominant,Because each core can handle one thread(同一时刻).

二、线程的引入

1、使用线程技术同时读取键盘和鼠标

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
char buf[200];
void *func(void* arg)
{

while(1){

memset(buf,0,sizeof(buf));
printf("before read.\n");
read(0,buf,5);
printf("读出键盘的内容是:[%s].\n", buf);
}
}
int main(void)
{

int ret=-1;int fd=-1;
pthread_t th=-1;//线程id
ret=pthread_create(&th,NULL,func,NULL);//创建线程-Child thread keyboard
if(ret<0){

perror("open");return -1;
}
while(1){
//Main thread mouse
memset(buf,0,sizeof(buf));
printf("before read.\n");
read(fd,buf,50);
printf("读出鼠标的内容是:[%s].\n",buf);
}
return 0;
}

2、Linux 中的线程简介

  • (1)线程是一种轻量级进程.
  • (2)线程是参与内核调度的最小单元.
  • (3)一个进程中可以有多个线程.

3、线程技术的优势

  • (1)像进程一样可被 OS 调度.
  • (2)It is easy to communicate efficiently between multiple threads of the same process.
  • (3)在多核心 CPU 架构(对称多处理器架构 SMP)maximize efficiency.

4、线程间通信方式

  • (1)信号:用 pthread_kill Signal the thread,The target thread needs to use sigaction 来处理.
  • (2)信号量(计数器):用于同步,A thread blocks and waits for another thread to send it a semaphore before continuing
  • (3)锁机制
    • ①互斥锁:Used to protect shared data or keep operations mutually exclusive.
    • ②条件变量:与信号量类似,Used with mutexes,对条件的测试是在互斥锁的保护下进行的.Condition variables are used with mutex locks
    • ③自旋锁:When the lock is locked by another thread,Then the current thread is around the lock“旋转”,The loop instruction is executed repeatedly, 占用 CPU 时间.
    • 读写锁:一种特殊的自旋锁,写独占、读共享,It is suitable for the situation where the number of reads to the data structure is much greater than the number of writes.

三、线程常见函数

1.线程创建与回收

  • pthread_creat:主线程用来创建子线程
  • pthread_join:主线程用来(阻塞)等待回收子线程
  • pthread_detach:主线程用来分离子线程,分离后主线程不必再去回收子线程

2.线程取消

  • pthread_cancel:其他线程调用该函数去取消(结束)子线程
  • pthread_setcancelstate:子线程用来设置自己是否允许被取消
  • pthread_setcanceltype:子线程用来设置自己取消类型(立即取消or等执行到属于cancellation point 的函数的时候才会取消)

3.线程函数退出

  • pthread_exit与return:都可用于线程函数退出,注意exit是用于进程退出
  • pthread_cleanup_push与pthread_cleanup_pop:It is related to the cleanup function that needs to be called when the root thread exits

4.获取线程 ID

  • pthread_self

5.发送信号

  • pthread_kill

四、线程同步之信号量

task1
The user enters any character from the terminal and ends with the Enter key,The program counts and displays it,输入“end”则结束.

  • (1)使用多线程实现:The main thread gets user input and decides whether to end the program,Then send a semaphore to the child thread, 子线程(阻塞)Wait for the semaphore then exit the child thread or count and print.
  • (2)信号量的引入:
    • sem_init:信号量初始化
    • sem_post:发送信号量,表示当前状态.
    • sem_wait:that is used to judge,能用就用,Can't wait
    • sem_destroy:销毁信号量
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
char buf[200]={
0};
sem_t sem;
unsigned int flag=0;
void* func(void* arg)// 子线程程序,作用是统计 buf 中的字符个数并打印
{

//子线程首先应该有个循环,
//循环中阻塞在等待主线程激活的时候,After the child thread is activated, it is acquiredbuf中的字符
//长度,然后打印;完成后再次被阻塞
sem_wait(&sem);
while(flag==0){
//while(strncmp(buf,"end",3)!=0)
printf("本次输入了%d 个字符\n", strlen(buf));
memset(buf,0,sizeof(buf));
sem_wait(&sem);
}
pthread_exit(NULL);//return;Can be used for function thread exit
}
int main()
{

int ret=-1;pthread th=-1;
sem_init(&sem,0,0);
ret=pthread(&th,NULL,func,NULL);
if(ret!=0){

perror("pthread");exit(-1);//exitfunction to exit the process
}
printf("输入一个字符串,以回车结束.\n");
while(scanf("%s",buf)){

// 去比较用户输入的是不是 end,如果是则退出,如果不是则继续
if(!strcmp(buf,"end",3)){

printf("程序结束\n");flag = 1;
sem_post(&sem);
break;
}
//The main thread goes to signal the activation of the child thread to count.
//子线程被阻塞,主线程可以激活,这就是线程的同步问题
sem_post(&sem);
}
//回收子线程
printf("等待回收子线程\n");
ret=pthread_join(th,NULL);
if (ret != 0){

printf("pthread_join error.\n");exit(-1);
}
printf("子线程回收成功\n");
sem_destroy(&sem);return 0;
}

五、线程同步之互斥锁

1.什么是互斥锁

  • (1)互斥锁又叫互斥量,A mutex can only be locked once,So when the mutex is locked,other mutual A variable must be locked if it wants to be locked(阻塞)Wait for the mutex to be unlocked,So it can be used for thread synchronization.
  • ( 2 ) 相 关 函 数 : pthread_mutex_init 、 pthread_mutex_destory 、 pthread_mutex_lock 、 pthread_mutex_unlock
  • (3)互斥锁和信号量的关系:A mutex can be thought of as a special kind of semaphore.
  • (4)互斥锁主要用来实现关键段保护.

2.Use the mutex to realize the function of the previous section

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <pthread.h> 
char buf[200] = {
0};
pthread_mutex_t mutex;
unsigned int flag = 0;
// 子线程程序,作用是统计 buf 中的字符个数并打印 
void *func(void *arg)
{

//while (strncmp(buf, "end", 3) != 0) 
sleep(1);
while (flag == 0) {

pthread_mutex_lock(&mutex);
printf("本次输入了%d 个字符\n", strlen(buf));
memset(buf, 0, sizeof(buf));
pthread_mutex_unlock(&mutex);
sleep(1);
}
pthread_exit(NULL);
}
int main()
{

int ret=1-;pthread th=-1;
pthread_mutex_init(&mutex,NULL);
if (ret != 0) exit(-1);
printf("输入一个字符串,以回车结束\n");
while (1){

pthread_mutex_lock(&mutex);
scanf("%s", buf);
pthread_mutex_unlock(&mutex);
// 去比较用户输入的是不是 end
if (!strncmp(buf, "end", 3)){

printf("程序结束\n");flag = 1;break;
}
sleep(1);
}
printf("等待回收子线程\n");
ret = pthread_join(th, NULL);
if (ret != 0) exit(-1);
printf("子线程回收成功\n");
pthread_mutex_destroy(&mutex);return 0;
}

六、线程同步之条件变量

1.什么是条件变量

  • 条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程“(阻塞)Hangs while waiting for the condition to be met”,另一个线程使“条件成立”.
  • 为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起.

2.相关函数

  • pthread_cond_init
  • pthread_cond_destroy
  • pthread_cond_wait
  • pthread_cond_signal/pthread_cond_broacast

3、3.Use condition variables to implement the functions in the previous section.

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <pthread.h> 
char buf[200] = {
0};
pthread_mutex_t mutex;pthread_cond_t cond; //条件变量,Use with mutex locks
unsigned int flag = 0;
// 子线程程序,作用是统计 buf 中的字符个数并打印
void* func(void* arg)
{

while(flag==0){

pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
printf("本次输入了%d 个字符\n", strlen(buf));
memset(buf, 0, sizeof(buf));
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
int main(void)
{

int ret=-1;pthread_t th=-1;
pthread_mutex_init(&mutex,NULL);pthread_cond_init(&cond,NULL);
ret=pthread_crate(&th,NULL,func,NULL);
if(ret!=0) exit(-1);
printf("输入一个字符串,以回车结束\n");
while (1){

scanf("%s", buf);
pthread_cond_signal(&cond);
// 去比较用户输入的是不是 end,如果是则退出,如果不是则继续
if (!strncmp(buf, "end", 3)){

printf("程序结束\n");flag = 1;break;
}
}
printf("等待回收子线程\n");
ret = pthread_join(th, NULL);
if (ret != 0) exit(-1);
printf("子线程回收成功\n");
pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond);
return 0;
}

For detailed thread introduction, please see my other blog线程同步

copyright:author[Brother Dong's practice diary],Please bring the original link to reprint, thank you. https://en.javamana.com/2022/218/202208061356108714.html