函數(shù)原型:
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg);
返回值:若是成功建立線程返回0,否則返回錯誤的編號
形式參數(shù): pthread_t *restrict tidp 要創(chuàng)建的線程的線程id指針
const pthread_attr_t *restrict attr 創(chuàng)建線程時的線程屬性
void* (start_rtn)(void) 返回值是void類型的指針函數(shù) vodi
*restrict arg start_rtn的行參 例題1: 功能:測試建立一個新的線程 程序名稱: pthread_test.c
#include <pthread.h>
#include <stdio.h>
void *create(void *arg)
 ...{
printf("new thread created ..... ");
}
int main(int argc,char *argv[])
 ...{
pthread_t tidp;
int error;

error=pthread_create(&tidp,NULL,create,NULL);
if(error!=0)
 ......{
printf("pthread_create is not created ... ");
return -1;
}
printf("prthread_create is created... ");
return 0;
}

編譯方法:
#gcc -Wall -lpthread pthread_test.c
因為pthread的庫不是linux系統(tǒng)的庫,所以在進行編
譯的時候要加上-lpthread,否則編譯不過,會出現(xiàn)下面錯誤
thread_test.c: 在函
數(shù) ‘create’ 中:
thread_test.c:7: 警告: 在
有返回值的函數(shù)中,程序流程到達(dá)函數(shù)尾
/tmp/ccOBJmuD.o: In function `main':thread_test.c:(.text+0x4f):對
‘pthread_create’未定義的引用
collect2: ld 返回 1
現(xiàn)在我們能建立了一個線程了,我們可以從函數(shù)的原型看到,在創(chuàng)建線程的時候,是可以在對
我們的函數(shù)進行傳遞參數(shù),在pthread_create的第四個行參。我們看一下例題2~3. 例題2
功能:向新的線程傳遞整形值 程序名稱:pthread_int.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *create(void *arg)
 ...{
int *num;
num=(int *)arg;
printf("create parameter is %d ",*num);
return (void *)0;
}
int main(int argc ,char *argv[])
 ...{
pthread_t tidp;
int error;
int test=4;
int *attr=&test;
error=pthread_create(&tidp,NULL,create,(void *)attr);

if(error!=0)
 ...{
printf("pthread_create is created is not created ... ");
return -1;
}
sleep(1);
printf("pthread_create is created is created ... ");
return 0;
}
編譯方法:
gcc -lpthread thread_int.c -Wall
執(zhí)行結(jié)果:
create parameter is 4
pthread_create is created is created ...
例題總結(jié):
可以看出來,我們在main函數(shù)中傳遞的整行指針,傳遞到我們新建的線程函數(shù)中。
在上面的例子可以看出來我們向新的線程傳入了另一個線程的int數(shù)據(jù),線程之間還可以傳遞字符串或是更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
例題3:
程序功能:向新建的線程傳遞字符串 程序名稱:thread_char.c
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *create(void *arg)
 ...{
char *name;
name=(char *)arg;
printf("arg is %s
",name);
return (void *)0;
}
int main(int argc,char *argv[])
 ...{
char *a="wang";
int error;
pthread_t tidp;

error=pthread_create(&tidp,NULL,create,(void *)a);

if(error!=0)
 ...{
printf("pthread is not created
");
return -1;
}
sleep(1);
printf("pthread is created...
");
return 0;
}

編譯方法:
gcc -Wall thread_char.c -lpthread

執(zhí)行結(jié)果:
arg is wang
pthread is created...
例題總結(jié):
可以看出來main函數(shù)中的字符串傳入了新建里的線程中。
例題4
程序名稱:thread_struct.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
 #include <stdlib.h> /**//*malloc()*/
struct test
 ...{
int a;
char *s;
};

void *create(void *arg)
 ...{
struct test *temp;
temp=(struct test *)arg;
printf("test->a ==%d
",temp->a);
printf("test->s ==%s
",temp->s);
return (void *)0;
}
int main(int argc,char *argv[])
 ...{
pthread_t tidp;
int error;
struct test *b;
b=(struct test *)malloc(sizeof(struct test));
b->a=4;
b->s="wang";

error=pthread_create(&tidp,NULL,create,(void *)b);

if(error!=0)
 ...{
printf("phread is not created...
");
return -1;
}
sleep(1);
printf("pthread is created...
");
return 0;
}

編譯方法:
gcc -Wall -lpthread thread_struct.c
執(zhí)行結(jié)果:
test->a ==4
test->s ==wang
pthread is created...
線程包含了標(biāo)識進程內(nèi)執(zhí)行環(huán)境必須的信息。他集成了進程中的所有信息都是對線程進行共享
的,包括文本程序、程序的全局內(nèi)存和堆內(nèi)存、棧以及文件描述符。
例題5
程序目的:驗證新建立的線程可以共享進程中的數(shù)據(jù) 程序名稱:thread_share.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
static int a=4;
void *create(void *arg)
 ...{
printf("new pthread ...
");
printf("a==%d ",a);
return (void *)0;
}
int main(int argc,char *argv[])
 ...{
pthread_t tidp;
int error;
a=5;

error=pthread_create(&tidp,NULL,create,NULL);

if(error!=0)
 ...{
printf("new thread is not create ...
");
return -1;
}
sleep(1);
printf("new thread is created ...
");
return 0;
}

編譯方法:
gcc -Wall -lpthread thread_share.c

執(zhí)行結(jié)果:
new pthread ...
a==5
new thread is created ...

例題總結(jié):可以看出來,我們在主線程更改了我們的全局變量a的值的時候,我們新建立的線程則打印出來了改變的值,可以看出可以訪問線程所在進程中的數(shù)據(jù)信
息。
如果進程中任何一個線程中調(diào)用exit,_Exit,或者是_exit,那么整個進程就
會終止,與此類似,如果信號的默認(rèn)的動作是終止進程,那么,把該信號發(fā)送到線程會終止進程。 線程的正常退出的方式:
(1) 線程只是從啟動例程中返回,返回值是線程中的退出碼 (2) 線程可以被另一個進程進行終止 (3)
線程自己調(diào)用pthread_exit函數(shù) 兩個重要的函數(shù)原型:
#include <pthread.h>
void pthread_exit(void *rval_ptr);
/*rval_ptr 線程退出返回
的指針*/
int pthread_join(pthread_t thread,void **rval_ptr);
/*成功結(jié)束進程為0,否則為錯誤編碼*/
例題6 程序目的:線程正常退出,接受線程退出的返回碼
程序名稱:exit_return.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *create(void *arg)
 ...{
printf("new thread is created ...
");
return (void *)2;
}
int main(int argc,char *argv[])
 ...{
pthread_t tid;
int error;
void *temp;

error=pthread_create(&tid,NULL,create,NULL);

if(error!=0)
 ...{
printf("thread is not created ...
");
return -1;
}
error=pthread_join(tid,&temp);

if(error!=0)
 ...{
printf("thread is not exit ...
");
return -2;
}
printf("thread is exit code %d
",(int )temp);
sleep(1);
printf("thread is created...
");
return 0;
}

編譯方法:
gcc -Wall exit_return.c -lpthread
執(zhí)行結(jié)果:
new thread is created ...
thread is exit code 2
thread is created...
線程退出不僅僅可以返回線程的int數(shù)值,還可以返回一個復(fù)雜的數(shù)據(jù)結(jié)構(gòu) 例題7
程序目的:線程結(jié)束返回一個復(fù)雜的數(shù)據(jù)結(jié)構(gòu) 程序名稱:exit_thread.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
struct test
 ...{
int a;
char *b;
};

struct test temp=
 ...{
.a =4,
.b ="wang"
};

void *create(void *arg)
 ...{
printf("new thread ...
");
return (void *)&temp;
}

int main(int argc,char *argv[])
 ...{
int error;
pthread_t tid;
struct test *c;

error=pthread_create(&tid,NULL,create,NULL);
if(error!=0)
 ...{
printf("new thread is not created ...
");
return -1;
}
printf("main ...
");

error=pthread_join(tid,(void *)&c);

if(error!=0)
 ...{
printf("new thread is not exit ...
");
return -2;
}
printf("c->a ==%d
",c->a);
printf("c->b ==%s
",c->b);
sleep(1);
return 0;
}

編譯方法:
gcc -Wall -lpthread exit_struct.c
執(zhí)行結(jié)果:
main ...
new thread ...
c->a ==4
c->b ==wang

例題總結(jié):一定要記得返回的數(shù)據(jù)結(jié)構(gòu)要是在這個數(shù)據(jù)要返回的結(jié)構(gòu)沒有釋放的時候應(yīng)用,如果數(shù)據(jù)結(jié)構(gòu)已經(jīng)發(fā)生變化,那返回的就不會是我們所需要的,而是藏數(shù)
據(jù)阿。
函數(shù)原型:
 #include <pthread.h>  pthread_t pthread_self(void);
例題8 程序目的:實現(xiàn)在新建立的線程中打印該線程的id和進程id 程序名稱:thread_self.c
編譯方法:
 gcc -Wall -lpthread thread_self.c
執(zhí)行結(jié)果:
 Main thread is starting ...  main pid is 6860  new thread ....  thread_tid==3084954544  thread pid is 6860 
4、 線程的處理程序
函數(shù)原型:
 #include <pthread.h>  void pthread_cleanup_push(void (*rtn)(void *),void *arg); 函數(shù)rtn是清理函數(shù),arg是調(diào)用參數(shù)  void pthread_cleanup_pop(int execute); 
在前面講過線程的終止方式,是正常終止還是非正常終止,都會存在一個資源釋放的問題,在posix中提供了一組,就是我們上面看的函數(shù)進行線程退出的處理
函數(shù),有些像在進程中的atexit函數(shù)。釋放的方式是指pthread_cleanup_push的調(diào)用點到pthread_cleanup_pop之
間程序段進行終止。
pthread_cleanup_push()/pthread_cleanup_pop采用先入后出的方式的棧的管理方式,void
*rtn(void
*),在執(zhí)行pthread_cleanup_push()時壓入函數(shù)棧,多次執(zhí)行pthread_cleanup_push()形成一個函數(shù)鏈,在執(zhí)行
這個函數(shù)鏈的時候會以反方向彈出,即先入后出。execute參數(shù)表識,是否執(zhí)行彈出清理函數(shù),當(dāng)execute=0時不進行彈出清理函數(shù),非零的時候彈
出處理函數(shù)。
例題9
程序目的:實現(xiàn)在正常結(jié)束線程的時候,進行函數(shù)處理
程序名稱:thread_clean.c
編譯方法:
執(zhí)行結(jié)果:
 thread 1 start  thread 1 push complete  thread 1 exit code 1  thread 2 start  thread 2 push complete  cleanup :thread 2 second handler  cleanup :thread 2 first handler  thread 2 exit code 2 
 gcc -Wall -lpthread thread_clean.c
 #include <stdio.h>  #include <pthread.h>  #include <unistd.h>  void *clean(void *arg)   ...{  printf("cleanup :%s ",(char *)arg);  return (void *)0;  }  void *thr_fn1(void *arg)   ...{  printf("thread 1 start ");  pthread_cleanup_push(clean,"thread 1 first handler");  pthread_cleanup_push(clean,"thread 1 second hadler");  printf("thread 1 push complete ");  if(arg)   ...{  return((void *)1);  }  pthread_cleanup_pop(0);  pthread_cleanup_pop(0);  return (void *)1;  }  void *thr_fn2(void *arg)   ...{  printf("thread 2 start ");  pthread_cleanup_push(clean,"thread 2 first handler");  pthread_cleanup_push(clean,"thread 2 second handler");  printf("thread 2 push complete ");  if(arg)   ...{  pthread_exit((void *)2);  }  pthread_cleanup_pop(0);  pthread_cleanup_pop(0);  pthread_exit((void *)2);  }  int main(void)   ...{  int err;  pthread_t tid1,tid2;  void *tret;   err=pthread_create(&tid1,NULL,thr_fn1,(void *)1);  if(err!=0)   ...{  printf("error .... ");  return -1;  }  err=pthread_create(&tid2,NULL,thr_fn2,(void *)1);   if(err!=0)   ...{  printf("error .... ");  return -1;  }  err=pthread_join(tid1,&tret);  if(err!=0)   ...{  printf("error .... ");  return -1;  }  printf("thread 1 exit code %d ",(int)tret);   err=pthread_join(tid2,&tret);  if(err!=0)   ...{  printf("error .... ");  return -1;  }
 gcc -Wall -lpthread thread_clean.c
 printf("thread 2 exit code %d ",(int)tret);  exit(0);  } 
|