C语言实现一种创建易管理易维护线程的方法

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/qq_30650153/article/details/82153955

一、什么是线程?

在一个程序中的多个执行路线就叫做线程。
就个人理解而言,一个线程就是一个进程里的一个while(1),一般情况下线程是不会退出的。
而多线程自然就是一个进程里的多个while(1)了。
《西游记》中,有一种有趣的设定——“天上一天,地上一年”。
而在现实世界中,随着技术发展,CPU的性能越来越高,夸张点说:“CPU一年,地上一天”。
为了高效利用CPU性能,多进程的方式丰富了操作系统,无论是windows还是Linux系统,程序都是“轮班”跑的,放慢些看,就是这个运行一会儿,然后让出CPU,其他程序再运行一会儿,然而我们看起来就是同时运行的。
多线程也是这样的。

二、linux下线程函数

Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,在编译时注意加上-lpthread参数,以调用静态链接库;pthread并非Linux系统的默认库

1、pthread_create

  • pthread_create是UNIX环境创建线程函
  • int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict_attr,void*(*start_rtn)(void*),void *restrict arg);
  • 若成功则返回0,否则返回错误码
  • 第一个参数为指向线程标识符的指针;二个参数用来设置线程属性;第三个参数是线程运行函数的地址;最后一个参数是运行函数的参数

2、pthread_join

  • 函数pthread_join用来等待一个线程的结束
  • extern int pthread_join __P (pthread_t __th, void **__thread_return);
  • 如果执行成功,将返回0,失败则返回错误码
  • 第一个参数为被等待的线程标识符;第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。
  • 这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回
#include <stdio.h>
#include <pthread.h> 
void *threadfun(void *arg)
{
    printf("hello \n");
} 
 int main(void)
{
  pthread_t id;
  int i,ret;
  ret=pthread_create(&id,NULL,threadfun,NULL); 
  if(ret!=0) {
    printf ("Create pthread error!\n");
    exit (1);
  }
  pthread_join(id,NULL);
  return (0);
} 

补充:
printf("current thread id:%u\n", (unsigned int)pthread_self());可打印出当前线程id。

三、创建易管理易维护的线程

文件均为为给力同事所传。为防丢失忘记,因此记录于此。

1、优势:

  • 可设置优先级
  • 易查看

2、使用

在工程中加入下面的c文件和h文件。
在所用的地方包头文件,然后这样创建:

    static int port = 14000;
    printf("current thread id:%u\n", (unsigned int)pthread_self());
    ThreadCreateParaDef tThreadCreatePara;
    memset(&tThreadCreatePara, 0, sizeof(ThreadCreateParaDef));
    tThreadCreatePara.ps8Name = (char *)"receiveJobs";
    tThreadCreatePara.pvFuncPara = &port;
    tThreadCreatePara.EntryFuncPt = gSoapServerThread;
    createThread(&tThreadCreatePara);

3、查看步骤

ps -ef | grep fw_ro* 查看进程id

top -H -p 16002查看进程的线程,效果如下图:
PID为29527的线程即为receiveJobs线程。
这里写图片描述


4、附录

cbasethread.h

#ifndef CBAETHREAD_H
#define CBAETHREAD_H

typedef struct ThreadCreateParaDef
{
    char *ps8Name;                                              // 线程名称
    void *(*EntryFuncPt)(void *);                               // 线程入口函数
    void *pvFuncPara;                                           // 线程参数
    int s32OldCancelState;
    int s32OldCancelType;
}ThreadCreateParaDef;

int CreateThread(ThreadCreateParaDef *ptThreadCreatePara);

#endif // MSG_DISTRIBUTION_H

cbasethread.c

#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <memory.h>
#include <sys/prctl.h>
#include "cbasethread.h"


void *ThreadInterface(void *pvPara)
{
    ThreadCreateParaDef *ptThreadCreatePara = (ThreadCreateParaDef *)pvPara;
    void *pvFuncPara = ptThreadCreatePara->pvFuncPara;
    /*
    设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)
    和PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信
    号继续运行;old_state如果不为NULL则存入原来的Cancel状态以便恢复。
    */
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &ptThreadCreatePara->s32OldCancelState);
    /*
    设置本线程取消动作的执行时机,type有两种取值:PTHREAD_CANCEL_DEFERRED和
    PTHREAD_CANCEL_ASYNCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到
    信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如
    果不为NULL则存入运来的取消动作类型值。
    */
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &ptThreadCreatePara->s32OldCancelType);

    prctl(PR_SET_NAME, ptThreadCreatePara->ps8Name);

    if(NULL != pvPara)
    {
        free(pvPara);
    }

    (*ptThreadCreatePara->EntryFuncPt)(pvFuncPara);

    return NULL;
}

pthread_t TaskSpawn
(
    char *ps8Name,                                          /* 任务的名称 */
    int s32Priority,                                        /* 实时任务的优先级 1-99 */
    void *(*pvEntryPt)(void *),                             /* 任务的函数入口 */
    void *pvFuncPara,                                       /* 这是一个指针值,任务入口函数的入参 */
    int s32Schedule                                         /*指定fifo 、rr或者normal调度方法*/
)
{
    int ret = 0;
    struct sched_param tSchParam;
    pthread_attr_t tThreadAttr;
    pthread_t tThreadID;
    int s32SchPolicy;

    if(NULL == pvEntryPt)
    {
        return 0;
    }

    /*判断优先级的正确性*/
    if (s32Priority > 99 || s32Priority < 0)
    {
        return 0;
    }

    /*初始化线程参数*/
    pthread_attr_init(&tThreadAttr);

    /*设置调度策略*/
    pthread_attr_getschedpolicy(&tThreadAttr, &s32SchPolicy);
    s32SchPolicy = s32Schedule;                                       /*创建的所有任务都将是实时任务*/
    pthread_attr_setschedpolicy(&tThreadAttr, s32SchPolicy);

    /*设置进程为分离状态,任务分离后将不需要用pthread_join()等待线程退出*/
    pthread_attr_setdetachstate(&tThreadAttr, PTHREAD_CREATE_DETACHED);

    if (SCHED_FIFO == s32Schedule || SCHED_RR == s32Schedule)
    {
        /* 设置实时任务的优先级*/
        pthread_attr_getschedparam(&tThreadAttr, &tSchParam);
        tSchParam.sched_priority = s32Priority;
        pthread_attr_setschedparam(&tThreadAttr, &tSchParam);
    }

    ret = pthread_create(&tThreadID, &tThreadAttr, pvEntryPt, pvFuncPara);
    if(0 != ret)
    {
        perror(NULL);
        printf("TaskSpawn-%s create error", ps8Name);
        return 0;
    }

    return tThreadID;
}

int CreateThread(ThreadCreateParaDef *ptThreadCreatePara)
{
    pthread_t tThreadSysID;
    ThreadCreateParaDef *pthreadPara = NULL;

    pthreadPara = (ThreadCreateParaDef *)malloc(sizeof(ThreadCreateParaDef));
    memcpy(pthreadPara, ptThreadCreatePara, sizeof(ThreadCreateParaDef));

    tThreadSysID = TaskSpawn(ptThreadCreatePara->ps8Name, 1, ThreadInterface, pthreadPara, SCHED_RR);
    if(!tThreadSysID)                                                    // 线程启动有问题
    {
        printf("Thread startup error\n");
        if (pthreadPara != NULL)
        {
            free(pthreadPara);
        }
        return -1;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_30650153/article/details/82153955