Linux多线程

参考书籍:《从实践中学嵌入式linux应用程序开发》(华清远见嵌入式学院)

资料下载:http://download.csdn.net/detail/klcf0220/5333020

参考链接:http://www.cnblogs.com/skynet/archive/2010/10/30/1865267.html

http://www.ibm.com/developerworks/cn/linux/l-cn-mthreadps/

进程与线程
进程是程序执行时的一个实例,即它是程序已经执行到何种程度的数据结构的汇集。从内核的观点看,进程的目的就是担当分配系统资源(CPU时间、内存等)的基本单位。
线程是进程的一个执行流,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。一个进程由几个线程组成(拥有很多相对独立的执行流的用户程序共享应用程序的大部分数据结构),线程与同属一个进程的其他的线程共享进程所拥有的全部资源。
"进程——资源分配的最小单位,线程——程序执行的最小单位"
进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

线程:
创建线程:pthread_create()
退出线程:pthread_exit()
等待线程:pthread_join()
终止另一个线程结束:pthread_cancal()

简单线程实例:

/*pthread.c*/
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
char message[32] = "hello world";
void *func(void *arg)
{
    printf("thread_function is running,argument is %s\n",(char *)arg);
    strcpy(message,"marked by thread");
    pthread_exit("Thank you for the cpu time");
}
int main(int argc,char *argv[])
{
    pthread_t threadid;
    void *thread_result;
    if(pthread_create(&threadid,NULL,func,(void *)message) < 0)//使用缺省属性创建线程
    {
        perror("fail to pthread_create");
        exit(-1);
    }
    printf("waiting for thread to finnish\n");
    if(pthread_join(threadid,&thread_result) < 0)//等待线程结束
    {
        perror("fail to pthread_join");
        exit(-1);
    }
    printf("MESSAGE is now %s\n",message);
    return 0;
}
gcc –o pthread pthread.c –lpthread

线程之间的同步与互斥

        互斥锁是用一种简单的加锁方法来控制对共享资源的原子操作。这个互斥锁只有两种状态,也就是上锁和解锁,可以把互斥锁看作某种意义上的全局变量。在同一时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对共享资源进行操作。若其他线程希望上锁一个已经被上锁的互斥锁,则该线程就会挂起,直到上锁的线程释放掉互斥锁为止。可以说,这把互斥锁保证让每个线程对共享资源按顺序进行原子操作。

互斥锁线程控制:
1、互斥锁初始化:pthread_mutex_init()
2、互斥锁上锁:pthread_mutex_lock()
3、互斥锁判断上锁:pthread_mutex_trylock()
4、互斥锁解锁:pthread_mutex_unlock()
5、消除互斥锁:pthread_mutex_destroy()
互斥锁实例:

信号量线程控制:
信号量知识详见http://www.cnblogs.com/klcf0220/archive/2013/05/05/3061620.html

1、sem_init()
2、sem_wait()和sem_trywait() 都相当于P操作,在信号量 >0 时它们都能将信号量的值减1。两者的区别在于信号量 <0 时,sem_wait()将会阻塞进程,而sem_trywait()则会立即返回。
3、sem_post() 相当于V操作,它将信号量的值加1,同时发出信号来唤醒等待的进程;
4、sem_getcalue() 用于得到信号量的值
5、sem_destroy() 用于删除信号量

多线程实例:

“生产者——消费者”问

/*producer-customer.c*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<fcntl.h>
#include<errno.h>
#include<sys/ipc.h>
#include<semaphore.h>
#include<sys/types.h>
#define MYFIFO "myfifo"//缓冲区有名管道的名字
#define BUFFER_SIZE 3//缓冲区的单元数
#define UNIT_SIZE 5//每个单元的大小
#define RUN_TIME 30//运行时间
#define DELAY_TIME_LEVELS 5.0//周期的最大值
int fd;
time_t end_time;
sem_t mutex,full,avail;
//生产者线程
void *producer(void *arg)
{
    int real_write;
    int delay_time = 0;
    while(time(NULL) < end_time)
    {
        delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX) / 2.0) + 1;
        sleep(delay_time);
        //P操作信号量avail和mutex
        sem_wait(&avail);
        sem_wait(&mutex);
        printf("\nproducer:delay = %d\n",delay_time);
        //生产者写入数据
        if((real_write = write(fd,"hello",UNIT_SIZE)) == -1)
        {
            if(errno == EAGAIN)
            {
                printf("the FIFO has noe been read yet.\n");
            }
        }
        else
        {
            printf("write %d to the FIFO\n",real_write);
        }
        //V操作信号量full和mutex
        sem_post(&full);
        sem_post(&mutex);
    }
    pthread_exit(NULL);
}

//消费者线程
void *customer(void *arg)
{    
    unsigned char read_buffer[UNIT_SIZE];
    int real_read;
    int delay_time = 0;
    while(time(NULL) < end_time)
    {
        delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX) / 2.0) + 1;
        sleep(delay_time);
        memset(read_buffer,0,UNIT_SIZE);
        //P操作信号量full和mutex
        sem_wait(&full);
        sem_wait(&mutex);
        printf("\ncustomer:delay = %d\n",delay_time);
        //生产者写入数据
        if((real_read = read(fd,read_buffer,UNIT_SIZE)) == -1)
        {
            if(errno == EAGAIN)
            {
                printf("no data yet.\n");
            }
        }
        printf("read %s from FIFO.\n",read_buffer);
        //V操作信号量avail和mutex
        sem_post(&avail);
        sem_post(&mutex);
    }
    pthread_exit(NULL);
}

int main()
{
    pthread_t prd,cst,mon;
    int ret;
    srand(time(NULL));
    end_time = time(NULL) + RUN_TIME;
    //创建有名管道
    if((mkfifo(MYFIFO,O_CREAT|O_EXCL) < 0) && (errno != EEXIST))
    {
        printf("cannot create FIFO\n");
        return errno;
    }
    //打开管道
    fd = open(MYFIFO,O_RDWR);
    if(fd == -1)
    {
        printf("open FIFO error\n");
        return fd;
    }
    //初始化信号量
    ret = sem_init(&mutex,0,1);
    ret += sem_init(&avail,0,BUFFER_SIZE);
    ret += sem_init(&full,0,0);
    if(ret != 0)
    {
        printf("any sem_init failed\n");
        return ret;
    }
    //创建两个线程
    ret = pthread_create(&prd,NULL,producer,NULL);
    if(ret != 0)
    {
        printf("create producer thread failed\n");
        return ret;
    }
    ret = pthread_create(&cst,NULL,customer,NULL);
    if(ret != 0)
    {
        printf("create customer thread failed\n");
        return ret;
    }
    pthread_join(prd,NULL);
    pthread_join(cst,NULL);
    close(fd);
    unlink(MYFIFO);
    return 0;
}
gcc –o producer-customer producer-customer.c –lpthread
./producer-customer
作者:快乐出发0220 ;Android群:151319601 ; Linux群:96394158 ;转载请注明出处 http://klcf0220.cnblogs.com/ !!!
原文地址:https://www.cnblogs.com/klcf0220/p/3061002.html