Linux 下C语言多线程编程

进程与线程的区别

进程拥有独立的地址空间,而且进程间的数据空间也相互独立,数据的传递得通过通信的方式;

线程是在一个进程下同时运行,多个线程之间的数据共享

线程的启动

函数原型:

/* Create a new thread, starting with execution of START-ROUTINE
   getting passed ARG.  Creation attributed come from ATTR.  The new
   handle is stored in *NEWTHREAD.  */
extern int pthread_create (pthread_t *__restrict __newthread,
			   const pthread_attr_t *__restrict __attr,
			   void *(*__start_routine) (void *),
			   void *__restrict __arg) __THROWNL __nonnull ((1, 3));

第一个参数为指向线程标识符的指针;
第二个参数为线程的属性;
第三个参数是线程运行函数的起始地址;
第四个参数是运行函数的参数;
z注:返回0表示创建成功,非o创建失败;EAGAIN表示系统不允许创建(线程数量过多),EINVAL 第二个参数的属性非法

线程的退出

1 线程函数执行完返回

2 调用pthread_exit结束

相关函数

pthread_join函数

/* Make calling thread wait for termination of the thread TH.  The
   exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN
   is not NULL.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int pthread_join (pthread_t __th, void **__thread_return);

第一个参数为等待的线程的标识符

第二个参数为用户定义的指针,它可以用来存储被等待线程的返回值

:这个函数是一个线程阻塞函数,调用它将会一直等着被等带的线程函数执行完返回

pthread_detach函数

/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN.
   The resources of TH will therefore be freed immediately when it
   terminates, instead of waiting for another thread to perform PTHREAD_JOIN
   on it.  */
extern int pthread_detach (pthread_t __th) __THROW;

参数就是线程的标识符,一旦调用该函数,该线程就不能再调用pthread_join加入等待列表,线程函数执行完以后会立即释放资源,使用此函数时一般不关心执行结果。

pthread_exit函数

/* Terminate calling thread.

   The registered cleanup handlers are called via exception handling
   so we cannot mark this function with __THROW.*/
extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__));

参数是函数的返回值,只要pthread_join的第二个参数不是NULL,这个值将被传递给__thread_return

:一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程返回错误,错误代码:ESRCH

Demo 代码

#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "keyboard.h"

#define MAX_THREAD_COUNT 10

typedef struct thread_s {
    pthread_t thread;                //线程标志符
    void *(*start_routine)(void *);  //函数指针,需要执行的函数
    void *arg;                       //指针函数的参数
    int blocked;                     //线程运行状态标志
    int started;                     //现场启动标志
} thread_t;

static thread_t threads[MAX_THREAD_COUNT];  //定义一个静态数组存放线程信息
static int thread_cnt = 0;                  //已有线程的数据

static int quit = 0;  //标记是否退出线程

static void add_thread(void *(*start_routine)(void *), void *arg, int blocked) {
    if (thread_cnt >= MAX_THREAD_COUNT)
        return;
    threads[thread_cnt].start_routine = start_routine;
    threads[thread_cnt].arg = arg;
    threads[thread_cnt].blocked = blocked;
    threads[thread_cnt].started = 0;
    thread_cnt++;
}

static void start_thread(void) {
    int i;
    for (i = 0; i < thread_cnt; i++) {
        //创建一个线程
        if (pthread_create(&threads[i].thread, NULL, threads[i].start_routine,
                           threads[i].arg) == 0) {
            threads[i].started = 1;
        } else {
            fprintf(stderr, "%s(): cannot create thread %d\n", __FUNCTION__, i);
        }
    }
}

static void exit_thread(void) {
    int i;
    for (i = 0; i < thread_cnt; i++) {
        if (threads[i].started) {
            if (threads[i].blocked)
                pthread_kill(threads[i].thread, SIGHUP);
            pthread_join(threads[i].thread, NULL);
        }
    }
}

static void *test_thread_a(void *arg) {
    while (!quit) {
        //在这里添加需要执行的代码
        fprintf(stderr, "%s(): thread is running!\n", __FUNCTION__);
        sleep(2);
    }

    fprintf(stderr, "%s(): thread terminated!\n", __FUNCTION__);
}

static void *test_thread_b(void *arg) {
    while (1) {
        fprintf(stderr, "%s(): thread is running!\n", __FUNCTION__);
        sleep(3);
    }
    fprintf(stderr, "%s(): thread terminated!\n", __FUNCTION__);
}

int main(int argc, char **argv) {
    int _char;
    add_thread(test_thread_a, NULL, 0);
    add_thread(test_thread_b, NULL, 1);

    start_thread();

    //初始化键盘输入
    if (init_keyboard() != 0) {
        fprintf(stderr, "init_keyboard failed\n");
    } else {
        fprintf(stderr, "Press Q or q quit\n");
    }

    while (!quit) {
        //接收所有键盘输入的字符,如果有Q或者q就退出程序
        while ((_char = __getch()) >= 0) {
            if (_char == 'Q' || _char == 'q') {
                quit = 1;
                break;
            }
        }
        sleep(2);
    }

    close_keyboard();
    exit_thread();
    return 0;
}

完整代码

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章