Linux C多线程编程以及函数介绍

4 篇文章 0 订阅
2 篇文章 0 订阅

Introduction

首先介绍线程的概念,在网上有这么一段介绍

Thread is an execution unit which consists of its own program counter, a stack, and a set of registers. Threads are also known as Lightweight processes. Threads are popular way to improve application through parallelism. The CPU switches rapidly back and forth among the threads giving illusion that the threads are running in parallel.

As each thread has its own independent resource for process execution, multpile processes can be executed parallely by increasing number of threads.

 

结合其他的介绍,总结来说:

  1. 线程不是进程 但可以理解为轻量级进程 通常来说是进程的表亲  
  2. 多个线程可以共享产生它们的父进程的全部系统资源,包括虚拟地址空间、文件描述符、信号处理等等。
  3. 线程有自己的私有资源,例如计数器、栈、寄存器等。

 

多线程的优点

简单来说,在进程间切换相对于在线程间切换,开销要大很多,尤其是如果需要多个进程同时运行的话,频繁切换会造成很大的系统开销,可能我们的本意是通过多进程提高程序的运行速度,但是往往会发现,多进程之间的通信开销、系统切换的开销有时候会造成程序的执行速度反而降低了,这个时候就用到了多线程,由于多个线程之间可以共享父进程的资源,可以省去相当一部分进程间的通信开销,同时线程间的切换比进程间的切换要快很多,所以在一些程序中,使用多进程有明显的优势。

 

多线程编程

 

在开始正式编成之前,首先了解几个基本的函数:

复制部分英文原文介绍,以便深入理解函数的时候用到,

Linux manual page:

SYNOPSIS:

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


Compile and link with -pthread.

使用时需要添加pthread.h头文件,同时编译的时候需要指定-pthread

 

DESCRIPTION

The pthread_create() function starts a new thread in the calling
       process.  The new thread starts execution by invoking
       start_routine(); arg is passed as the sole argument of
       start_routine().
Before returning, a successful call to pthread_create() stores the ID
       of the new thread in the buffer pointed to by thread; this identifier
       is used to refer to the thread in subsequent calls to other pthreads
       functions.

 

 The attr argument points to a pthread_attr_t structure whose contents
       are used at thread creation time to determine attributes for the new
       thread; this structure is initialized using pthread_attr_init(3) and
       related functions.  If attr is NULL, then the thread is created with
       default attributes.

参数简介:

thread:用来存储线程的ID,在主程序里面可以使用,所以这个变量不能是局部变量,而是一个指针变量。

attr:指向一个结构体的指针,这个结构体可以定义创建函数的一些参数,如果使用NULL的话,这个线程会以默认的参数创建(Joinable).

strat_routine:第三个参数是一个函数指针,这个函数需要返回void*类型。

arg:传递给函数的参数。

NOTES        

       See pthread_self(3) for further information on the thread ID returned
       in *thread by pthread_create().  Unless real-time scheduling policies
       are being employed, after a call to pthread_create(), it is
       indeterminate which thread—the caller or the new thread—will next
       execute.

       A thread may either be joinable or detached.  If a thread is
       joinable, then another thread can call pthread_join(3) to wait for
       the thread to terminate and fetch its exit status.  Only when a
       terminated joinable thread has been joined are the last of its
       resources released back to the system.  When a detached thread
       terminates, its resources are automatically released back to the
       system: it is not possible to join with the thread in order to obtain
       its exit status.  Making a thread detached is useful for some types
       of daemon threads whose exit status the application does not need to
       care about.  By default, a new thread is created in a joinable state,
       unless attr was set to create the thread in a detached state (using
       pthread_attr_setdetachstate(3)).

       Under the NPTL threading implementation, if the RLIMIT_STACK soft
       resource limit at the time the program started has any value other
       than "unlimited", then it determines the default stack size of new
       threads.  Using pthread_attr_setstacksize(3), the stack size
       attribute can be explicitly set in the attr argument used to create a
       thread, in order to obtain a stack size other than the default.  If
       the RLIMIT_STACK resource limit is set to "unlimited", a per-
       architecture value is used for the stack size.  Here is the value for
       a few architectures:
              ┌─────────────┬────────────────────┐
              │Architecture │ Default stack size │
              ├─────────────┼────────────────────┤
              │i386         │               2 MB │
              ├─────────────┼────────────────────┤
              │IA-64        │              32 MB │
              ├─────────────┼────────────────────┤
              │PowerPC      │               4 MB │
              ├─────────────┼────────────────────┤
              │S/390        │               2 MB │
              ├─────────────┼────────────────────┤
              │Sparc-32     │               2 MB │
              ├─────────────┼────────────────────┤
              │Sparc-64     │               4 MB │
              ├─────────────┼────────────────────┤
              │x86_64       │               2 MB │
              └─────────────┴────────────────────┘

 

以上是函数的一些详细介绍,以及函数特性。

DEMO

下面由实例运用一下:

 

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

void *print_message (void *msg);

int main()
{
    int tmp1, tmp2;
    void *retval;
    pthread_t thread1, thread2;
    char message1[] = "This is thread1";
    char message2[] = "This is thread2";

    int ret_thread1, ret_thread2;

    ret_thread1 = pthread_create(&thread1, NULL, print_message, (void *) message1);
    ret_thread2 = pthread_create(&thread2, NULL, print_message, (void *) message2);

    // 线程创建成功,返回0,失败返回失败号
    if (ret_thread1 != 0) {
        printf("线程1创建失败\n");
    } else {
        printf("线程1创建成功\n");
    }

    if (ret_thread2 != 0) {
        printf("线程2创建失败\n");
    } else {
        printf("线程2创建成功\n");
    }

    //同样,pthread_join的返回值成功为0
    tmp1 = pthread_join(thread1, &retval);
    //printf("thread1 return value(retval) is %d\n", (int*)retval);
    printf("thread1 return value(tmp) is %d\n", tmp1);
    if (tmp1 != 0) {
        printf("cannot join with thread1\n");
    }
    printf("thread1 end\n");

    tmp2 = pthread_join(thread2, &retval);
    //printf("thread2 return value(retval) is %d\n", (int*)retval);
    printf("thread2 return value(tmp) is %d\n", tmp1);
    if (tmp2 != 0) {
        printf("cannot join with thread2\n");
    }
    printf("thread2 end\n");

}

void *print_message( void *msg ) {
    int i = 0;
    for (i; i<5; i++) {
        printf("%s:%d\n", (char *)msg, i);
    }
}

需要注意的几点:

1 pthread_create函数调用的函数应该是一个返回void*类型的。

2 函数执行成功会返回0,其余的错误都不为0.

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值