线程概述

 

clone函数调用
    #include <sched.h>
    int clone(int (*fn)(void *fnarg), void *child_stack, int flags, void *arg, ...
                 /* pid_t *pid, struct user_desc *tls, pid_t *ctid */ );
    int __clone2(int (*fn)(void *),  void *child_stack_base,size_t stack_size, int flags, void *arg, ...
                 /* pid_t *pid, struct user_desc *tls, pid_t *ctid */ );
    指向子进程执行时调用的函数,fnarg是传给该函数的参数,child_stack是你为子进程分配的堆栈指针,flags通过将下表中的值相或得到,arg被传送给子函数,他的取值和用法完全有你决定,因为他为函数提供了上下文,用他从父进程向任何子进程传送数据,clone返回创建进程的进程ID,出错的话返回-1,设置errno,并不建立子进程。
    CLONE_VM                若设置,父子进程运行在同一段内存
    CLONE_FS                若设置,父子进程共享在root文件系统,当前工作目录以及umask信息
    CLONE_FILES         若设置,父子信息共享文件描述服
    CLONE_SIGHAND       若设置,父子进程共享在父进程上的信号处理器
    CLONE_PID           若设置,父子进程具有相同的PID

pthread接口
    一,建立一个新的线程
        #include <pthread.h>
        int pthread_create(pthread_t *restrict thread,
              const pthread_attr_t *restrict attr,
              void *(*start_routine)(void*), void *restrict arg);
        thread用来保存新线程的标识符,attr决定了对线程应用哪种线程属性,start_routine指向线程要执行的函数的指针,arg他是传递给前面的函数的参数,如果他有意义,则由用户来定义。pthread_create()执行成功返回0,并在thread中保存线程的标识符,失败则返回一个非零的退出码。
    二,结束一个线程
        #include <pthread.h>
        void pthread_exit(void *value_ptr);
        pthread_exit()函数用来终止当前的线程,并返回valure_ptr,该值可由父线程或其他线程通过pthread_join来检索。一个线程也可以简单的从其初始化函数的返回来终止。
    三,等待一个线程结束
        #include <pthread.h>
        int pthread_join(pthread_t thread, void **value_ptr);
        函数pthread_join()用来挂起当前的线程,直到thread指定的线程运行结束为止。thread用来指定线程,value_ptr为用户定义的一个指针,他可以用来存储等待进程的返回值。其他线程不能对同一线程再应用pthread_join函数。
    四,登记函数
        #include <pthread.h>
        int pthread_atfork( void (*prepare)(void),  /*在创建新线程之前调用*/
                                    void (*parent)(void),   /*在父线程中随后调用*/
                                    void (*child)(void));   /*建立好子线程后立即在子线程中调用*/
        pthread_atfork()函数登记三个函数,用来在某个时间来调用。他们都可以为NULL,此时,对应的函数将不发生调用。可以通过多次调用pthread_atfork函数登记多组处理函数。如果执行成功返回0,否则返回出错代码。注意,在即将出台的POSIX线程标准中,将不再包含pthread_atfork的调用。
    五,取消线程
        #include <pthread.h>
        int pthread_cancel(pthread_t thread);
        int pthread_setcancelstate(int state, int *oldstate);
        int pthread_setcanceltype(int type, int *oldtype);
        void pthread_testcancel(void);
        pthread_cancel用来取消thread指定的线程,pthread_setcancelstate用来设置他的取消状态,state是新状态,oldstate用来保存旧的状态,他可以是NULL,state的值可以是:
            PTHREAD_CANCEL_ENABLE   允许请求取消
            PTHREAD_CANCEL_DISABLE  忽略取消请求
        pthread_setcanceltype用来改变一个线程对取消请求的响应方式,type的取值可以是:
            PTHREAD_CANCEL_ASYNCHRONOUS 立即取消
            PTHREAD_CANCEL_DEFERRED         延迟取消直至下一个取消点,取消点用pthread_setcancel来建立,如果有任何正被挂起的取消请求,这个函数就会取消当前的线程,还类函数中,如果成功返回0,否则返回出错代码。
    六,线程结束处理
        #include <pthread.h>
        void pthread_cleanup_pop(int execute);
        void pthread_cleanup_push(void (*routine)(void*), void *arg);
        当在线程中调用pthread_exit或者线程允许取消请求,而又到达一个取消点时,就调用routine函数,并将arg作为参数。处理函数被压入一个栈中,所以,当使用pthread_cleanup_pop时,取消最近的一个压入的函数,如果execute不为0,表明栈中还有可用的处理函数,此时,也会被执行,POSIX标准要求,每一个入栈操作都要对应一个出栈操作。
    七,线程挂起
        #include <pthread.h>
        pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
        int pthread_cond_destroy(pthread_cond_t *cond);
        int pthread_cond_init(pthread_cond_t *restrict cond,
              const pthread_condattr_t *restrict attr);
        int pthread_cond_broadcast(pthread_cond_t *cond);
        int pthread_cond_signal(pthread_cond_t *cond);
        int pthread_cond_timedwait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex,
              const struct timespec *restrict abstime);
        int pthread_cond_wait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex);
        函数pthread_cond_init()用来初始化一个cond_t类型的对象,Linux中会忽略第二个参数,大多数的Linux的pthread程序只是简单的把PTHREAD_COND_INITIALIZER复制给attr,函数pthread_cond_destory()是cond_t类型对象的析构器,检查有没有线程正在等待条件的情况。pthread_cond_signal用来重启一个并且唯一的一个正在等待条件的进程 ,pthread_cond_broatcase与pthread_cond_signal的区别是他会重启所有正在等待条件的线程。这两个函数中的cond参数表示条件。pthread_cond_wait用来解开mutex指出的一个互斥锁,然后等待变量cond上的信号,pthread_cond_timedwait函数的功能与此类似,但他只等待abstime指定的时间。上述所有的函数成功后返回0,而在出错时返回错误代码。
    八,线程比较
        #include <pthread.h>
        int pthread_equal(pthread_t t1, pthread_t t2);
        这个函数用来比较线程ID t1,t2引用的是不是同一个线程,是则返回0,否则返回非0;
    九,线程属性
        线程的属性控制着一个线程在他整个生命周期的行为,
        属性                值                                  含义
        datachstatc     PTHREAD_CREATE_JOINABLE     可切入的状态
                            PTHREAD_CREATE_DETACHED     被分离的状态
        schedpolicy     SCHED_OTHER                     正常,非实时
                            SCHED_RR                            实时,循环
                            SCHED_FIFO                      实时,先入先出
        schedparam      与策略有关
        inheritsched    PTHREAD_EXPLICIT_SCHED      由schedpolice和schedparam设置,从
                            PTHREAD_INHERIT_SCHED       父进程继承
        scope               PTHREAD_SCOPE_SYSTEM            一个线程一个系统时间片,线程共享系统
                            PTHREAD_SCOPE_PROCESS       时间片(Linux不支持)
        下列函数控制者线程属性对象,注意,这些调用不能控制和线程直接相关联的属性,产生的属性对象通常要传递给pthread_create函数。
        #include <pthread.h>
        int pthread_attr_destroy(pthread_attr_t *attr);
        int pthread_attr_init(pthread_attr_t *attr);
        int pthread_attr_getdetachstate(const pthread_attr_t *attr,
              int *detachstate);
        int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
        int pthread_attr_getschedpolicy(const pthread_attr_t *restrict attr,
              int *restrict policy);
        int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
        int pthread_attr_getschedparam(const pthread_attr_t *restrict attr,
              struct sched_param *restrict param);
        int pthread_attr_setschedparam(pthread_attr_t *restrict attr,
              const struct sched_param *restrict param);
        int pthread_attr_getinheritsched(const pthread_attr_t *restrict attr,
              int *restrict inheritsched);
        int pthread_attr_setinheritsched(pthread_attr_t *attr,
              int inheritsched);
        int pthread_attr_getscope(const pthread_attr_t *restrict attr,
              int *restrict contentionscope);
        int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope);
    十,互斥
        用来保护被多个线程共享的数据不会被同时修改。一个互斥锁只有两种状态,加锁与解锁,加锁的互斥不但不让其他线程访问,而且互斥也规上锁进程所有,任何进程都能访问解锁互斥,但他却不归任何线程所有。
        #include <pthread.h>
        pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
        int pthread_mutex_destroy(pthread_mutex_t *mutex);
        int pthread_mutex_init(pthread_mutex_t *restrict mutex,
              const pthread_mutexattr_t *restrict attr);
        int pthread_mutex_lock(pthread_mutex_t *mutex);
        int pthread_mutex_trylock(pthread_mutex_t *mutex);
        int pthread_mutex_unlock(pthread_mutex_t *mutex);
        pthread_mutex_init函数创建指针mutex指向的互斥,并且用mutexattr指定的属性初始化该互斥。
        互斥属性
        属性                                                    描述                    备注
        PTHREAD_MUTEX_INITIALIZER                       创建一个快速互斥        调用线程被阻塞直至拥有互斥的线程解锁为止
        PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP      创建一个递归互斥        不阻塞调用进程,但返回一个出错代码EDEADLK
        PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP 创建一个检错互斥        成功返回并增加调用线程上锁的次数,但必须拥有同样次数的解锁
        除了使用mutex参数,还可以使用下面的初始化过程静态创建pthread_mutex_t变量。
        pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
        pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
        pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;       
 

#include <pthread.h>

#include <stdlib.h>

#include <stdio.h>

#include <unistd.h>

 

int i = 0;

int j = 0;

 

void test1(int * num);

void test2(int * num);

int main(void)

{

    pthread_t pt1, pt2;

   

    if (pthread_create(&pt1, NULL, (void *)test1, (void *)&i))

    {

        perror("Creat pthread test1 error\n");

        exit(EXIT_FAILURE);

    }

    if (pthread_create(&pt2, NULL, (void *)test2, (void *)&j))

    {

        perror("Creat thread  test2 error\n");

        exit(EXIT_FAILURE);

    }

   

    pthread_join(pt1, NULL);

    pthread_join(pt2, NULL);

   

    printf("Total = %d\n",i + j);

   

    return 0;

}

 

void test1(int * num)

{

    int i = 0;

   

    while (i++ < 5)

        printf("In test1 : i = %d\n", (*num)++);

    sleep(5);

    while (0 < i--)

        printf("In test1 -after sleep : i = %d\n",(*num)++);

}

 

void test2(int * num)

{

    int i = 0;

   

    while (i++ < 4)

        printf("In test2 : j = %d\n", (*num)++);

    sleep(8);

       

    while (0 < i--)

        printf("In test2 -after sleep : j = %d\n", (*num)++);

}

 

#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

 

void test1(char * str)

{

    int i = 0;

    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);

    while (i < 5)

        printf("%s : i = %d\n", str, i++);

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

    pthread_testcancel();

    puts("Error!");

    sleep(3);

    while (0 < i)

        printf("%s : i = %d\n", str, i--);

}

int main(void)

{

    pthread_t thread1;

 

    pthread_create(&thread1, NULL, (void *)test1, (void *)"thread 1");

 

    pthread_cancel(thread1);

    pthread_join(thread1, NULL);

 

    puts("Back to main");

    return 0;

}

你可能感兴趣的:(JOIN,thread,struct,null,asynchronous,Signal)