3G模块SIM5360E Linux编程1——主线程

一、主线程的流程图

在这里插入图片描述

二、主线程的代码

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
 
int getreq(char *buf,int bufsize);
void *internet(void *ptr);
void *message(void *ptr);
 
//定义一个结构体
 
typedef struct _Req_Exc
{
    int                 req;
    int                 exc;
    pthread_mutex_t     lock;
}Req_Exc;
 
int main(int argc,char **argv)
{
    pthread_t           tid_msg,tid_net;    //线程ID
    pthread_attr_t      thread_attr;        //线程属性
    Req_Exc             req_exc;
    char                cmd_buf[16];
 
    Req_Exc *ptr = &req_exc;                //指针指向结构体
    ptr->req = 0;
    ptr->exc = 0;
 
    //初始化锁
 
    pthread_mutex_init(&req_exc.lock, NULL);
 
    //初始化线程
    
    if( pthread_attr_init(&thread_attr) )
    {
        printf("pthread_attr_init() failure: %s\n",strerror(errno));
        goto Cleanup;
    }
 
    if( pthread_attr_setstacksize(&thread_attr,120*1024) )
    {
        printf("pthread_attr_setstacksize() failure: %s\n",strerror(errno));
        goto Cleanup;
    }
 
    if( pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) )
    {
        printf("pthread_attr_setdetachstate() failure: %s\n",strerror(errno));
        goto Cleanup;        
    }
 
    //创建子线程
 
    if( pthread_create(&tid_msg,&thread_attr,message,(void *)ptr) !=0 )
    {
        printf("pthread create [message] failure: %s\n",strerror(errno));
        goto Cleanup;
    }
 
    if( pthread_create(&tid_net,&thread_attr,internet,(void *)ptr) !=0 )
    {
        printf("pthread create [internet] failure: %s\n",strerror(errno));
        goto Cleanup;
    }
 
    //摧毁线程属性
 
    pthread_attr_destroy(&thread_attr);
 
    printf("\nWelcome!\n");
    printf("Please input 'internet' or 'message'\n");
    printf("Please input the command:\n");
    
    while(1)
    {
        fgets(cmd_buf,sizeof(cmd_buf),stdin);
    
        if( getreq(cmd_buf,sizeof(cmd_buf)) == 1 )
        {
            pthread_mutex_lock(&req_exc.lock);//上锁
            ptr->req = 1;
            pthread_mutex_unlock(&req_exc.lock);//释放锁
        }
 
        else if( getreq(cmd_buf,sizeof(cmd_buf)) == 2 )
        {
            pthread_mutex_lock(&req_exc.lock);//上锁
            ptr->req = 2;
            pthread_mutex_unlock(&req_exc.lock);//释放锁
        }
 
        else if( getreq(cmd_buf,sizeof(cmd_buf)) == 0 )
        {
            printf("req number is not 1 or 2 !\n");
        }
 
        //想要发短信但是有上网的情况
 
        if( ptr->req == 2 )
        {
            if( ptr->exc !=0 )
            {
                //关掉上网线程
 
                pthread_cancel(tid_net);
                sleep(1);
                printf("Close the internet thread\n");
 
                //重新打开上网线程
 
                if(pthread_create(&tid_net,&thread_attr,internet,(void *)ptr) != 0)
                {
                    printf("pthread create [internet] failure: %s\n",strerror(errno));
                    goto Cleanup;
                }
 
                printf("Restart the internet thread\n");
 
                //发短信操作
 
                printf("正在发短信,等待10秒\n");
                sleep(10);
                printf("\n发短信成功!\n");
 
                pthread_mutex_lock(&req_exc.lock);//上锁
                ptr->req = 0;
                ptr->exc = 0; 
                pthread_mutex_unlock(&req_exc.lock);//释放锁
            }
        }
    }
 
    pthread_mutex_destroy(&req_exc.lock);
 
    return 0;
 
Cleanup:
        pthread_mutex_destroy(&req_exc.lock);
        pthread_attr_destroy(&thread_attr);
        return -1;
 
}
 
//上网
 
void *internet(void *ptr)
{
    int oldstate;
    int oldtype;
    Req_Exc *temp_pctr = (Req_Exc *)ptr;
 
    //使能可取消该线程
 
    if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&oldstate) != 0)
    {
        printf("setcanclesate failure:%s\n",strerror(errno));
        exit(-1);
    }
 
    //设置取消类型,异步取消,不遇到取消点
 
    if(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&oldtype) != 0)
    {
        printf("pthread_setcanceltype failure:%s\n",strerror(errno));
        exit(-1);
    }
 
    while(1)
    {
        if( temp_pctr->req == 1 )
        {
            printf("请求上网\n");
 
            if( temp_pctr->exc == 0 )
            {
                pthread_mutex_lock(&temp_pctr->lock);//上锁
                temp_pctr->exc = temp_pctr->req;
                pthread_mutex_unlock(&temp_pctr->lock);//释放锁
            
                //上网操作
 
                printf("正在上网,等待2秒\n");
                sleep(2);
                printf("\n上网成功!\n");
 
                pthread_mutex_lock(&temp_pctr->lock);//上锁
                temp_pctr->req = 0;
                temp_pctr->exc = 0;
                pthread_mutex_unlock(&temp_pctr->lock);//释放锁
            }
            else
            {
                printf("正在使用发短信功能...\n");
                sleep(1);
            }
        }
    }
}
 
//发短信
 
void *message(void *ptr)
{
    Req_Exc *temp_pctr = (Req_Exc *)ptr;
 
    while(1)
    {
        if( temp_pctr->req == 2 )
        {   
            if( temp_pctr->exc == 0 )
            {
                printf("请求发短信\n");
 
                pthread_mutex_lock(&temp_pctr->lock);//上锁
                temp_pctr->exc = temp_pctr->req;
                pthread_mutex_unlock(&temp_pctr->lock);//释放锁
 
                //发短信操作
 
                printf("正在发短信,等待10秒\n");
                sleep(10);
                printf("\n发短信成功!\n");
 
                pthread_mutex_lock(&temp_pctr->lock);//上锁
                temp_pctr->req = 0;
                temp_pctr->exc = 0;
                pthread_mutex_unlock(&temp_pctr->lock);//释放锁
            }
        }
    }
}
 
//获取req值
 
int getreq(char *buf,int bufsize)
{
    char        buf_new[16];
 
    strncpy(buf_new,buf,bufsize);
 
    if(strcmp(buf_new,"message\n") == 0)
    {
        return 2;
    }
    else if(strcmp(buf_new,"internet\n") == 0)
    {
        return 1;
    }
    else
    {
        printf("Command error!\n");
        return 0;
    }
}

三、编译生成的结果

编译

gcc main_pthread.c -l pthread

运行

./a.out

结果
在这里插入图片描述

四、总结

在写代码和调试过程中遇到了许多问题,以下是我遇到的问题和解决方法或者思路:

  1. 问题一:流程图画得不够好!
    第一次自己动手画流程图,画了好几个版本,我觉得一开始的思路不能乱,想的东西不能多。比如,上面的发短息和上网的流程,可以先画“一路顺畅”的,遇到要阻塞或者判断的,先画一个判断框,等基本流程好了之后再考虑画其他分支。
  2. 问题二:对线程的理解不够!
    在main()函数里面的子线程创建,我一开始以为是子线程的声明,傻了吧唧在后面又引用了一下子线程。我打印了一下,发现怎么出现了两次线程,于是我问了一下别人,原来是在main()函数里面使用pthread_create()就是子线程的引用了。
  3. 问题三:pthread_create()第四个参数
    其实第四个参数是指针,我们要把结构体指针传给子线程,但是子线程函数入口要求传的是void *类型,所以要把第四个参数进行强制类型转换,具体实例:pthread_create(&tid_msg,&thread_attr,message,(void *)ptr)。子线程里面也要记得强制类型转换。
  4. 关于锁的问题
pthread_mutex_lock(&req_exc.lock);//上锁
pthread_mutex_unlock(&req_exc.lock);//释放锁

它锁的是地址,我一开始以为锁的是值,我一开始用的是ptr->lock,搞了半天才知道。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值