Skip to content

Latest commit

 

History

History
200 lines (153 loc) · 5.6 KB

24.md

File metadata and controls

200 lines (153 loc) · 5.6 KB

Linux Programing -- ch12-- POSIX 线程

在 linux 2.6 以前, pthread 线程库对应的实现是一个名叫 linuxthreads 的 lib. linuxthreads 利用前面提到的轻量级进程来实现线程。 到了 linux 2.6, glibc 中有了一种新的 pthread 线程库 NPTL(Native POSIX Threading Library). NPTL 实现了前面提到的 POSIX 的全部 5 点要求. 但是, 实际上, 与其说是 NPTL 实现了, 不如说是 linux 内核实现了.在 linux 2.6 中, 内核有了线程组的概念, task_struct 结构中增加了一个 tgid(thread group id)字段. 如果这个 task 是一个"主线程", 则它的 tgid 等于 pid, 否则 tgid 等于进程的 pid(即主线程的 pid),此外,每个线程有自己的 pid。

2. API

#include <pthread.h>

int pthread_create(pthread_t *thread, pthread_attr_t * attr, void*(*start_routine)(void *), void *arg);
void pthread_exit(void *retval);
int pthread_join(pthread_t thread, void **thread_return)

例程:

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

void *thread_function(void *arg);

char message[] = "hello word";

int main(int argc, char *argv[])
{
    int res;
    pthread_t a_thread;
    void *thread_result;

    res = pthread_create(&a_thread, NULL, thread_function, (void*)message);
    if(res != 0){
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    printf("Waiting for thread to finish...\n");
    res = pthread_join(a_thread, &thread_result);
    if(res != 0){
        perror("Thread jion failed\n");
        exit(EXIT_FAILURE);
    }
    printf("Thead joined, it return %s\n", (char*)thread_result);
    printf("Message now is %s\n", message);
    exit(EXIT_SUCCESS);
}

void *thread_function(void *arg)
{
    printf("thread_fuction is runing...argument is %s\n", (char*)arg);
    sleep(5);
    strcpy(message, "Bye!");
    pthread_exit("Thank you for your cup tiome\n");
}

3. 线程同步--信号量

#include <semaphore.h>

int sem_int(sem_t *sem, int pshared, unsigned int value); // pshare 用于进程间共享, linux 暂不支持,值为0
int sem_wait(sem_t *sem);
int sem_post(sem_t * sem);
int sem_destroy((sem_t *sem);

post 操作给信号量加 1,wait 操作给信号量减 1 但是他会阻塞知道信号量有个非零值才做减法操作。 sem_trywaitsem_wait的非阻塞版本。

例程:

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

sem_t sem;
void *thread_function(void *arg);

#define WORK_SIZE 1024
char work_area[WORK_SIZE];

int main(int argc, char *argv[])
{
    int res;
    pthread_t a_thread;
    void *thread_result;

    res = sem_init(&sem, 0, 0);
    if(res != 0){
        perror("Init semaphore failed\n");
        exit(EXIT_FAILURE);
    }

    res = pthread_create(&a_thread, NULL, thread_function, NULL);
    if(res != 0){
        perror("Create thread failed\n");
        exit(EXIT_FAILURE);
    }

    printf("Input some text. Enter 'end' to finish..\n");
    while(strncmp("end", work_area, 3) != 0){
        fgets(work_area, WORK_SIZE, stdin);
        sem_post(&sem);
    }

    printf("Waiting for the thread to finish...\n");
    res = pthread_join(a_thread, &thread_result);
    if(res != 0){
        perror("thread join failed\n");
        exit(EXIT_FAILURE);
    }

    printf("Thread joined\n");
    sem_destroy(&sem);
    exit(EXIT_SUCCESS);
}

void *thread_function(void *arg){
    sem_wait(&sem);
    while(strncmp("end", work_area, 3) != 0){
        printf("you input %d characters\n", strlen(work_area) - 1);
        sem_wait(&sem);
    }

    pthread_exit(NULL);
}

在上面的例程中有一个问题,假设计算字符个数的线程运行速度比主线程慢(可以在线程中加入一段 sleep),那么久会出现字符还没被计算出来字符数组 work_area 的内容就被改变了,也就是说这时候的限号量大于 1 了。

4. 线程同步--互斥量

#include <pthread.h>

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
int phtread_mutex_lock(pthread_mutex_t *mutex);
int phtread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(phtread_mutex_t *mutex);

5.线程属性

#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);

int pthread_attr_setdetachstate(pthread_attr_t * attr, int detachstate);
int pthread_attr_getdetachstate(phtread_attr_t *attr,, int *detachstate);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *policy);
int pthread_attr_setschedparam(pthread_attr_t  * attr,  const struct sched_param *param);
int pthread_attr_getschedparam(const pthread_attr_t  * attr,  const struct sched_param *param);
int pthread_attr_setinheritsched(pthread_attr_t   *attr, int inherit);
int pthread_attr_getinheritsched(const pthread_attr_t   *attr, int *inherit);
int pthread_attr_setscope(pthread_attr_t  *attr, int scope);
int pthread_attr_getscope(const pthread_attr_t *attr, int *scope);
int pthread_attr_setstacksize(pthread_attr_t *attr, int size);
int pthread_attr_setstacksize(const pthread_attr_t *attr, int *size);

6. 取消线程

#include <.pthread.h>

int pthread_cancel(pthread_t thread);
#include <.pthread.h>

int pthread_setcancelstate(in state, int *oldstate);

PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_DISABLE

#include <.pthread.h>

int pthread_stecanceltype(int state, int *oldstate);

PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_DEFERRED

7. 没了

线程的知识很多,这里做个粗略的总结