• linux系统编程:线程原语


                                     线程原语

    线程概念

       线程(thread),有时被称为轻量级进程(Lightweight Process,LWP)。是程序运行流的最小单元。一个标准的线程由线程ID。当前指令指针(PC),寄存器集合和堆栈组成。

    很多其他详解看百度百科:线程

    在Linux shell下通过命令 $ ps -Lf pid 查看指定pid号下的全部线程。


    线程之间的共享与非共享

    这里的线程是指同一进程下的线程。

    共享:

       1.文件描写叙述符表
       2.每种信号的处理方式
       3.当前工作文件夹
       4.用户ID和组ID
       5.内存地址空间

    非共享:

       1.线程id
       2.处理器现场和栈指针(内核栈)
       3.独立的栈空间(用户空间栈)
       4.errno变量
       5.信号屏蔽字
       6.调度优先级


    线程原语

    通过命令 $ man -k pthread 查看系统下与线程有关的全部函数。

    一般的,把main函数称作主线程或主控线程,其他线程都称作是子线程。

    创建线程

    #include <pthread.h>
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);

    pthread_t *thread:传递一个pthread_t变量地址进来,用于保存新线程的tid(线程ID)

    const pthread_attr_t *attr:线程属性设置。如使用默认属性,则传NULL

    void *(*start_routine)(void *):函数指针。指向新线程应该载入运行的函数模块

    void *arg:指定线程将要载入调用的那个函数的參数

    返回值:成功返回0,失败返回错误号。

    曾经学过的系统函数都是成功返回0,失败返回-1。而错误号保存在全局变量errno中,而pthread库的函数都是通过返回值返回错误号,尽管每一个线程也都有一个errno,但这是为了兼容其他函数接口而提供的,pthread库本身并不使用它。通过返回值返回错误码更加清晰。
    Compile and link with -lpthread.
    typedef unsigned long int pthread_t;   //在不同的系统中pthread_t可能会有不同的实现


    结束线程

    假设须要仅仅终止某个线程而不终止整个进程。能够有三种方法:

    1.return。

    这样的方法对主控线程不适用。从main函数return相当于调用exit。

    2.一个线程能够调用pthread_cancel终止同一进程中的还有一个线程。

    #include <pthread.h>
    int pthread_cancel(pthread_t thread);
    被取消的线程,退出值。定义在Linux的pthread库中常数PTHREAD_CANCELED的值是-1。能够在头文件pthread.h中找到它的定义:#define PTHREAD_CANCELED ((void *) -1)。也就是说,被pthread_cancel结束的线程,退出值,都是-1。

    同一进程的线程间,pthread_cancel向还有一线程发终止信号。

    系统并不会立即关闭被取消线程,仅仅有在被取消线程下次系统调用时,才会真正结束线程。

    或调用pthread_testcancel,让内核去检測是否须要取消当前线程。

    3.线程能够调用pthread_exit终止自己。

    #include <pthread.h>
    void pthread_exit(void *retval);
    void *retval:线程退出时传递出的參数。能够是退出值或地址,如是地址时,不能是线程内部申请的局部地址。
           

    在不论什么地方调用exit,都会使整个进程退出。


    线程id

    #include <pthread.h>
    pthread_t pthread_self(void);
    RETURN VALUE
    This function always succeeds, returning the calling thread’s ID.
    在线程中使用pthread_self。获取线程id。



    回收线程

    #include <pthread.h>
    int pthread_join(pthread_t thread, void **retval);
    pthread_t thread:回收线程的tid
    void **retval:接收退出线程传递出的返回值
    返回值:成功返回0。失败返回错误号
    同进程相似,线程退出后,相同须要进行回收,所以pthread_join相似于wait。调用该函数的线程将挂起等待,直到id为thread的线程终止。thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的。总结例如以下:
    1. 假设thread线程通过return返回,retval所指向的单元里存放的是thread线程函数的返回值。

    2. 假设thread线程被别的线程调用pthread_cancel异常终止掉,retval所指向的单元里存放的是常数PTHREAD_CANCELED。
    3. 假设thread线程是自己调用pthread_exit终止的。retval所指向的单元存放的是传给pthread_exit的參数。
    假设对thread线程的终止状态不感兴趣,能够传NULL给retval參数。


    代码演示样例

    使用return和pthread_exit结束进程

    //thread_exit.c
    #include <stdio.h>
    #include <unistd.h>
    #include <pthread.h>
    void *fun_1(void *argv)
    {
    	printf("Hello %s,my thread id is %x
    ", (char*)argv, pthread_self());
    	sleep(1);
    	//pthread_exit((void*)1);
    	return (void*)1;
    }
    void *fun_2(void *argv)
    {
    	printf("Hello %c, my thread id is %x
    ", (char)argv, pthread_self());
    	sleep(2);
    	pthread_exit((void*)"David");
    }
    int main(void)
    {
    	int *ret1;
    	char *ret2;
    	pthread_t tid1, tid2;
    	pthread_create(&tid1, NULL, fun_1, (void*)"zhangxiang");
    	pthread_create(&tid2, NULL, fun_2, (void*)'D');
    	pthread_join(tid1, (void*)&ret1);
    	pthread_join(tid2, (void*)&ret2);
    	printf("thread %x exit with %x
    ", tid1, ret1);
    	printf("thread %x exit with %s
    ", tid2, ret2);
    	return 0;
    }
    $ gcc thread_exit.c -lpthread
    $ ./a.out
    Hello D, my thread id is 745e9700
    Hello zhangxiang, my thread id is 74fea700
    thread 74fea700 exit with 1
    thread 745e9700 exit with David
           

    使用pthread_cancel终止还有一个线程

    //thread_cancel.c
    #include <stdio.h>
    #include <pthread.h>
    void *fun(void *argv)
    {
    	printf("thread %x running
    ", pthread_self());
    	pthread_exit((void*)0);
    }
    int main(void)
    {
    	pthread_t tid;
    	void *ret;
    	pthread_create(&tid, NULL, fun, NULL);
    	pthread_join(tid, &ret);
    	printf("thread %x exit with %d
    ", tid, (int)ret);
    	pthread_create(&tid, NULL, fun, NULL);
    	pthread_cancel(tid);
    	pthread_join(tid, &ret);
    	printf("thread %x exit with %d
    ", tid, (int)ret);
    	return 0;
    }
    $ gcc thread_cancel.c -lpthread
    $ a.out
    thread 96da9700 running
    thread 96da9700 exit with 0
    thread 96da9700 running
    thread 96da9700 exit with -1


    既能够在主线程中使用pthread_cancel终止子线程。也能够在子线程中终止还有一个子线程。




    CCPP Blog 文件夹


  • 相关阅读:
    JSP数据交互(一)
    response.setHeader()用法
    Vue初步认识
    Socket初步了解
    DOM4j的修改删除方式
    多线程
    ArrayList和Vector区别
    集合框架(一)
    深入C#数据类型
    深入.NET框架
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5389944.html
Copyright © 2020-2023  润新知