[ 永遠的UNIX::UNIX技術資料的寶庫 ]   GB | BIG5

首頁 > 編程技術 > C/C++ > 正文
Linux下C語言編程--線程操作
http://linuxc.51.net 作者:hoyt (2001-05-08 11:43:15)
前言:Linux下線程的創建 
    介紹在Linux下線程的創建和基本的使用. Linux下的線程是一個非常復雜的問題,由我對線程的學習不時很好,我在這裡只是簡單的介紹線程的創建和基本的使用,關線程的高級使用(如線程的屬性,線程的互斥,線程的同步等等問題)可以參考我面給出的資料. 現在關線程的資料在網絡上可以找到許多英文資料,面我羅列了許多鏈接,對線程的高級屬性感興趣的話可以參考一下. 等到我對線程的了解比較深刻的時候,我回來完成這篇文章.如果您對線程了解的詳盡我也非常高興能夠由您來完善. 
先介紹什是線程.我們編寫的程序大多數可以看成是單線程的.就是程序是按照一定的順序來執行.如果我們使用線程的話,程序就會在我們創建線成的地方分叉,變成兩個"程序"在執行.粗略的看來好象和子進程差不多的,其實不然.子進程是通過拷貝父進程的地址空間來執行的.而線程是通過共享程序代碼來執行的,講的通俗一點就是線程的相同的代碼會被執行幾次.使用線程的好處是可以節省資源,由線程是通過共享代碼的,所以沒有進程調度那復雜. 

線程的創建和使用
線程的創建是用下面的幾個函數來實現的. 

#include 
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 *thread,void **thread_return);

pthread_create創建一個線程,thread是用來表明創建線程的ID,attr指出線程創建時候的屬性,我們用NULL來表明使用缺省屬性.start_routine函數指針是線程創建成功開始執行的函數,arg是這個函數的唯一一個參數.表明傳遞給start_routine的參數. pthread_exit函數和exit函數類似用來退出線程.這個函數結束線程,釋放函數的資源,並在最阻塞,直到其他線程使用pthread_join函數等待它.然將*retval的值傳遞給**thread_return.由這個函數釋放所以的函數資源,所以retval不能夠指向函數的局部變量. pthread_join和wait調用一樣用來等待指定的線程. 下面我們使用一個實例來解釋一下使用方法.在實踐中,我們經常要備份一些文件.下面這個程序可以實現當前目錄下的所有文件備份.備份的綴名為bak 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 

#define BUFFER 512

struct copy_file {
int infile;
int outfile;
};

void *copy(void *arg)
{
   int infile,outfile;
   int bytes_read,bytes_write,*bytes_copy_p;
   char buffer[BUFFER],*buffer_p;
   struct copy_file *file=(struct copy_file *)arg;
  
   infile=file->infile;
   outfile=file->outfile;
   
/* 因為線程退出時,所有的變量空間都要被釋放,所以我們只好自己分配內存了 */
   if((bytes_copy_p=(int *)malloc(sizeof(int)))==NULL) pthread_exit(NULL);
   bytes_read=bytes_write=0;
   *bytes_copy_p=0;
  
/* 還記得怎拷貝文件嗎 */
   while((bytes_read=read(infile,buffer,BUFFER))!=0)
    {
if((bytes_read==-1)&&(errno!=EINTR))break;
else if(bytes_read>0)
         {
   buffer_p=buffer;
   while((bytes_write=write(outfile,buffer_p,bytes_read))!=0)
    {
if((bytes_write==-1)&&(errno!=EINTR))break;
else if(bytes_write==bytes_read)break;
else if(bytes_write>0)
 {
buffer_p+=bytes_write;
bytes_read-=bytes_write;
 }
    }
 if(bytes_write==-1)break;
 *bytes_copy_p+=bytes_read;
        }  
    }
   close(infile);
   close(outfile);
   pthread_exit(bytes_copy_p);
}

int main(int argc,char **argv)
{
  pthread_t *thread;
  struct copy_file *file;
  int byte_copy,*byte_copy_p,num,i,j;
  char filename[BUFFER];
  struct dirent **namelist;
  struct stat filestat;

/* 得到當前路徑下面所有的文件(包含目錄)的個數 */
  if((num=scandir(".",&namelist,0,alphasort))<0)
   {
fprintf(stderr,"Get File Num Error:%s\n\a",strerror(errno));
exit(1);
   }

/* 給線程分配空間,其實沒有必要這多的 */
  if(((thread=(pthread_t *)malloc(sizeof(pthread_t)*num))==NULL)||
     ((file=(struct copy_file *)malloc(sizeof(struct copy_file)*num))==NULL))
   {
fprintf(stderr,"Out Of Memory!\n\a");
exit(1);
   }

  for(i=0,j=0;i   {
memset(filename,'\0',BUFFER);
strcpy(filename,namelist[i]->d_name);
if(stat(filename,&filestat)==-1)
 {
        fprintf(stderr,"Get File Information:%s\n\a",strerror(errno));
                exit(1);
         }

/* 我們忽略目錄 */
if(!S_ISREG(filestat.st_mode))continue;
if((file[j].infile=open(filename,O_RDONLY))<0)
 {
      fprintf(stderr,"Open %s  Error:%s\n\a",filename,strerror(errno));
           continue;
     }

strcat(filename,".bak");
        if((file[j].outfile=open(filename,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))<0)
         {
             fprintf(stderr,"Creat %s  Error:%s\n\a",filename,strerror(errno));
             continue;
         }

/* 創建線程,進行文件拷貝 */
if(pthread_create(&thread[j],NULL,copy,(void *)&file[j])!=0)
 fprintf(stderr,"Create Thread[%d] Error:%s\n\a",i,strerror(errno));
j++;
  }
 
  byte_copy=0;
  for(i=0;i   {
/* 等待線程結束 */
if(pthread_join(thread[i],(void **)&byte_copy_p)!=0)
 fprintf(stderr,"Thread[%d] Join Error:%s\n\a",
i,strerror(errno));
else
         {
   if(bytes_copy_p==NULL)continue;
   printf("Thread[%d] Copy %d bytes\n\a",i,*byte_copy_p);
   byte_copy+=*byte_copy_p;
/* 釋放我們在copy函數裡面創建的內存 */
   free(byte_copy_p);
         }
   }
 printf("Total Copy Bytes %d\n\a",byte_copy);
 free(thread);
 free(file);
 exit(0);
}

線程的介紹就到這裡了,關線程的其他資料可以查看下面這寫鏈接.
Getting Started With POSIX Threads
The LinuxThreads library
 
 
(http://www.fanqiang.com)
    進入【UNIX論壇

相關文章
Linux下C語言編程--線程操作 (2001-05-08 11:43:15)
Linux下C語言編程--進程通信、消息管理 (2001-05-08 11:38:03)
Linux下C語言編程--信號處理函數 (2001-05-08 11:35:28)
Linux下C語言編程--時間概念 (2001-05-08 11:34:12)
Linux下C語言編程--文件的操作 (2001-05-08 11:33:15)
Linux下C語言編程--進程的創建 (2001-05-08 11:32:30)
Linux下C語言編程--基礎知識 (2001-05-08 11:31:29)
 

★  樊強制作 歡迎分享  ★