日期:2014-05-16  浏览次数:20716 次

linux下的简单进程创建
1. 进程是资源分配的最小单位,而线程是调度的最小单位。
2. 进程有独立的地址空间,拥有自己的代码段数据段堆栈段,而线程只有独立的堆栈段;
3. 进程拥有多种通信方式,而线程之间通信只有通过全局变量或者创建时传值。

之所以要使用多线程
1.和进程相比,它是一种非常节约的多任务操作方式。启动一个新进程,必须分配给它独立的地址空间
建立众多的数据表来维护它的代码段数据段和堆栈段,而创建一个进程中的线程,他们公用相同的地址
空间,共享大部分数据,启动一个线程所话费的时间远远小于一个进程。
2.线程间通信非常方便。不同的进程中通信,不仅费时,而且很不方便,线程则不然,由于同一个进程下的
线程共享数据空间,所以一个线程的数据可以直接为其他线程使用。
线程的创建方法,使用pthread_crpthread_t在头文件/usr/include/bits/pthreadtypes.h中定义:
  typedef unsigned long int pthread_t;
  它是一个线程的标识符。函数pthread_create用来创建一个线程,它的原型为:
  extern int pthread_create __P ((pthread_t *__thread, __const pthread_attr_t *__attr,
  void *(*__start_routine) (void *), void *__arg));
  第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。这里,我们的函数thread不需要参数,所以最后一个参数设为空指针。第二个参数我们也设为空指针,这样将生成默认属性的线程。对线程属性的设定和修改我们将在下一节阐述。当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL。前者表示系统限制创建新的线程,例如线程数目过多了;后者表示第二个参数代表的线程属性值非法。创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线
程则继续运行下一行代码。

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

struct menber
{
    int a;
    char *s;
};

/*
 * 线程执行函数
 * */
void *create(void *arg)
{
    struct menber *temp;
    temp=(struct menber *)arg;
    printf("menber->a = %d  \n",temp->a);
    printf("menber->s = %s  \n",temp->s);
    return (void *)0;
}

/*
 * 程序入口
 * */
int main(int argc,char *argv[])
{
    pthread_t tidp;
    int error;
    struct menber *b;

	/*为结构体指针b分配内存并赋值*/
    b=(struct menber *)malloc( sizeof(struct menber) );
    b->a = 4;
    b->s = "zieckey";
    
	/*创建线程并运行线程执行函数*/
    error = pthread_create(&tidp, NULL, create, (void *)b);
    if( error )
    {
        printf("phread is not created...\n");
        return -1;
    }

    sleep(1); //进程睡眠一秒使线程执行完后进程才会结束

    printf("pthread is created...\n");
    return 0;
}


由运行结果可以看到,线程打印出了在主函数中赋值的结构体,将这个结构体的值传入了线程中使用。

在Linux中,默认情况下是在一个线程被创建后,必须使用此函数对创建的线程进行资源回收,但是可以设置Threads attributes来设置当一个线程结束时,直接回收此线程所占用的系统资源,详细资料查看Threads attributes。
其实在Linux中,新建的线程并不是在原先的进程中,而是系统通过一个系统调用clone()。该系统copy了一个和原先进程完全一样的进程,并在这个进程中执行线程函数。不过这个copy过程和fork不一样。 copy后的进程和原先的进程共享了所有的变量,运行环境。这样,原先进程中的变量变动在copy后的进程中便能体现出来。

pthread_join的应用

pthread_join使一个线程等待另一个线程结束。
代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。
所有线程都有一个线程号,也就是Thread ID。其类型为pthread_t。通过调用pthread_self()函数可以获得自身的线程号。
测试代码: