part7 linux线程全解

再论进程

多进程实现同时读取键盘和鼠标

open的O_NONBLOCK宏表示非阻塞式打开

int main(void)
{
    //创建子进程,父子进程分别进程读键盘和鼠标的工作
    int ret = -1,fd = -1;
    char buf[200];

    ret = fork();
    if(ret < 0)
    {
        perror("fork:");
        return -1;
    }else 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 read.\n");
            read(fd, buf, 50);
            printf("读出的鼠标内容是: [%s].\n", buf);
        }
    }else
    {
        //父进程
        while(1)
        {
            memset(buf, 0, sizeof(buf));
            printf("before read.\n");
            read(0, buf, 2);
            printf("读出的键盘内容是: [%s].\n", buf);
        }
    }
       return 0;
}


使用进程技术的优势

CPU时分复用,单核心CPU可以实现宏观上的并行
实现多任务系统需求(多任务的需求是客观的)

使用进程技术的劣势

进程间切换开销大
进程间通信麻烦效率低

线程的引入

线程保留了进程技术实现多任务的特性
线程的改进就是在线程间切换和线程间通信商提升了效率
多线程在多核心CPU商更有优势

多线程实现同时读取键盘和鼠标

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>

void *func(void *arg)
{
    char buf[200];
    //线程函数
    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,fd = -1;
    char buf[200];
    pthread_t th = -1;
    //创建线程
    ret = pthread_create(&th, NULL, func, NULL);
    if(ret != 0)
    {
        printf("pthread_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 read.\n");
        read(fd, buf, 50);
        printf("读出的鼠标内容是: [%s].\n", buf);
    }

       return 0;
}

编译命令:gcc 3.7.2.c -lpthread  //-l链接函数库

linux中线程简介

一种轻量级的进程
线程是参与内核调度的最小单位
一个进程可以有多个线程

线程技术的优势

像进程一样可以被OS单独调度
同一个进程的多个线程之间很容易高效率通信
在多核心CPU(对称多处理器架构SMP)架构下效率最大化

线程常见函数

线程的创建与回收

pthread_create        主线程用来创造子线程
pthread_join            主线程用来等待(阻塞)回收子进程
pthread_detach       主线程用来分离子线程,分离后主线程不必再回首子线程

线程取消

pthread_cancel                              一般都是主线程调用该函数去取消子线程
pthread_setcancelstate                  子进程设置自己是否允许被取消
pthread_setcanceltype                   

线程函数退出机制

pthread_exit与return退出         
pthread_cleanup_push             
pthread_cleanup_pop                

获取线程id

pthread_self

线程同步之信号量

用户从终端输入任意字符然后统计个数显示,输入end则结束

使用多线程实现:主线程获取用户输入并判断是否退出,子线程计数

线程的同步问题:子线程被阻塞,主线程可以激活

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

char buf[200]={0};
sem_t sem;
//子线程程序,计数
void *func(void *arg)
{
    //子线程首先应该有个循环
    //循环总阻塞等待主线程激活,激活后获取buf长度,完成后再次阻塞
    sem_wait(&sem);
    while(strncmp(buf, "end", 3))
    {
        printf("输入了%ld个字符。\n", strlen(buf));
        memset(buf, 0, sizeof(buf));
        sem_wait(&sem);
    }
    pthread_exit(NULL);
}

int main(void)
{
    pthread_t th = -1,ret = -1;

    sem_init(&sem, 0, 0);//信号量初始化零
    ret = pthread_create(&th, NULL, func, NULL);
    if(ret != 0)
    {
        printf("pthread_create error.\n");
        return 0;
    }


    printf("输入一个字符串(以回车结束)。\n");

    while(scanf("%s", buf))
    {
        if(!strncmp(buf, "end", 3))
        {
            printf("程序结束\n");
            sem_post(&sem);
            break;
        }
        //主线程收到用户字符串,确定不是end后发信号激活子线程
        sem_post(&sem);
    }

    //回收子线程
    printf("等待回收子线程\n");
    ret = pthread_join(th, NULL);
    if(ret != 0)
    {
        printf("pthread_join error.\n");
        return 0;
    }
    printf("子线程回收成功\n");
    sem_destroy(&sem);

    return 0;
}

线程同步之互斥锁

互斥锁又叫互斥量(mutex)

相关函数:pthread_mutex_init    pthread_mutex_destroy     pthread_mutex_lock    pthread_mutex_unlock
互斥锁和信号量的关系:互斥锁是一种特殊的信号量,只有0和1的信号量
互斥锁主要用来实现关键段保护

用互斥锁来实现上述代码

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

char buf[200]={0};
pthread_mutex_t mutex;
int flag = 0;
//子线程程序,计数
void *func(void *arg)
{
    sleep(1);
    while(flag == 0)
    {
        pthread_mutex_lock(&mutex);
        sleep(0.5);
        printf("输入了%ld个字符。\n", strlen(buf));
        memset(buf, 0, sizeof(buf));
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
    pthread_exit(NULL);
}

int main(void)
{
    pthread_t th = -1,ret = -1;

    pthread_mutex_init(&mutex, NULL);
    ret = pthread_create(&th, NULL, func, NULL);
    if(ret != 0)
    {
        printf("pthread_create error.\n");
        return 0;
    }


    printf("输入一个字符串(以回车结束)。\n");

    while(1)
    {
        //上锁与解锁
        pthread_mutex_lock(&mutex);
        scanf("%s", buf);
        pthread_mutex_unlock(&mutex);
        if(!strncmp(buf, "end", 3))
        {
            printf("程序结束\n");
            flag = 1;
            break;
        }
        sleep(1);
    }

    //回收子线程
    printf("等待回收子线程\n");
    ret = pthread_join(th, NULL);
    if(ret != 0)
    {
        printf("pthread_join error.\n");
        return 0;
    }
    printf("子线程回收成功\n");

    pthread_mutex_destroy(&mutex);
    return 0;
}

线程同步之条件变量

相关函数:
pthread_cond_init          pthread_cond_destroy
pthread_cond_wait        pthread_cond_signal / pthread_cond_broadcast

使用条件变量实现上述代码

 

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

char buf[200]={0};
pthread_mutex_t mutex;
int flag = 0;
pthread_cond_t conde;///
//子线程程序,计数
void *func(void *arg)
{
    while(flag == 0)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&conde, &mutex);///
        printf("输入了%ld个字符。\n", strlen(buf));
        memset(buf, 0, sizeof(buf));
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(NULL);
}

int main(void)
{
    pthread_t th = -1,ret = -1;

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&conde, NULL);
    ret = pthread_create(&th, NULL, func, NULL);
    if(ret != 0)
    {
        printf("pthread_create error.\n");
        return 0;
    }


    printf("输入一个字符串(以回车结束)。\n");

    while(1)
    {
        scanf("%s", buf);
        pthread_cond_signal(&conde);///
        if(!strncmp(buf, "end", 3))
        {
            printf("程序结束\n");
            flag = 1;
            break;
        }
    }

    //回收子线程
    printf("等待回收子线程\n");
    ret = pthread_join(th, NULL);
    if(ret != 0)
    {
        printf("pthread_join error.\n");
        return 0;
    }
    printf("子线程回收成功\n");

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&conde);
    return 0;
}
  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值