1. 线程与进程的异同点
A.相同点
1): 比如都有自己在系统中唯一标识ID,一组寄存器(pc指针
),状态(6种),调度优先级以及所要遵循的调度策略。
2): 每个进程都有一个进程控制块,线程也拥有一个线程控制块(在Linux内核,线程控制块与进程控制块用同一个结 构体描述,即struct task_struct),这个控制块包含线程的一些属性信息,操作系统使用这些属性信息来描述线 程。
3): 线程和子进程的创建者可以在线程和子进程上实行某些控制,比如,创建者可以取消、挂起、继续和修改线程和 子进程的优先级。
B.不同点
1): 主要区别:每个进程都拥有自己的地址空间,但线程没有自己独立的地址空间,但是线程栈是线程专属的,而是运 行在一个进程里的所有线程共享该进程的整个虚拟地址空间。
2): 线程的上下文切换时间开销比进程上下文切换时间开销要小的多
3): 线程的创建开销远远小于进程的创建
4): 子进程拥有父进程的地址空间和数据段的拷贝,因此当子进程修改它的变量和数据时,它不会影响父进程中的数 据,但线程可以直接访问它进程中的数据段。
5): 进程之间通讯必须使用进程间通讯机制,但线程可以与进程中的其他线程直接通讯
6): 线程可以对同一进程中的其他线程实施大量控制,但进程只能对子进程实施控制
7): 改变主线程的属性可能影响进程中其他的线程,但对父进程的修改不影响子进程
2. 多进程文件拷贝程序:
<pre name="code" class="cpp">#include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> int copy_file_init(const char *src_file,const char *dest_file) { int fd_src; int fd_dest; int src_file_len; fd_src = open(src_file,O_RDONLY); if(fd_src < 0){ fprintf(stderr,"Fail to open %s : %s\n",src_file,strerror(errno)); exit(EXIT_FAILURE); } src_file_len = lseek(fd_src,0,SEEK_END); fd_dest = open(dest_file,O_WRONLY | O_TRUNC | O_CREAT,0666); if(fd_dest < 0){ fprintf(stderr,"Fail to open %s : %s\n",dest_file,strerror(errno)); exit(EXIT_FAILURE); } close(fd_src); close(fd_dest); return src_file_len; } int copy_file(const char *src_file,const char *dest_file,int postion,int len) { int n; int fd_src; int fd_dest; int count = 0; char buf[1024]; fd_src = open(src_file,O_RDONLY); if(fd_src < 0){ fprintf(stderr,"Fail to open %s : %s\n",src_file,strerror(errno)); exit(EXIT_FAILURE); } fd_dest = open(dest_file,O_WRONLY); if(fd_dest < 0){ fprintf(stderr,"Fail to open %s : %s\n",dest_file,strerror(errno)); exit(EXIT_FAILURE); } lseek(fd_src,postion,SEEK_SET); lseek(fd_dest,postion,SEEK_SET); while(1){ n = read(fd_src,buf,sizeof(buf)); if(n <= 0){ break; } n = write(fd_dest,buf,n); if(n <= 0){ break; } count += n; if(count >= len){ break; } } close(fd_src); close(fd_dest); return count; } void process_copy_file(const char *src_file,const char *dest_file,int src_file_len,int precess_num) { int n; int m=0; pid_t pid; pid = fork(); if(pid < 0){ perror("Fail to fork"); exit(EXIT_FAILURE); } if(pid == 0){ n = copy_file(src_file,dest_file,src_file_len/2,(src_file_len - src_file_len / 2)); printf("Child process copy %d bytes!\n",n); } if(pid > 0){ n = copy_file(src_file,dest_file,0,src_file_len / 2); printf("Parent process copy %d bytes!\n",n); } while(precess_num > 0){ pid = fork(); if(pid < 0){ perror("Fail to fork"); exit(EXIT_FAILURE); } else{ n--; } if } return ; } //./a.out src_file dest_file int main(int argc, const char *argv[]) { int src_file_len; if(argc < 3){ fprintf(stderr,"Usage : %s <src file> <dest file>!\n",argv[0]); exit(EXIT_FAILURE); } src_file_len = copy_file_init(argv[1],argv[2]); process_copy_file(argv[1],argv[2],src_file_len); exit(EXIT_SUCCESS); }
3. 多线程文件拷贝程序:
#include <stdio.h> #include <pthread.h> #include <string.h> #include <stdlib.h> #include <errno.h> //pthread_mutex_t lock; struct args{ char src_file[128]; char des_file[128]; int position; int len; }; int get_filelen(const char *src_file) { int len; FILE *fp; fp = fopen(src_file,"r"); fseek(fp,0,SEEK_END); len = ftell(fp); rewind(fp); return len; } void init_args(struct args *args ,const char *src_file,const char *des_file,int pos,int len) { strcpy(args->src_file, src_file); strcpy(args->des_file, des_file); args->position = pos; args->len = len; } void *copy_file(void *arg) { // pthread_mutex_lock(&lock); int n = 0; int ret; int count = 0; int read_len = 0; char buf[4096]; FILE *fp1,*fp2; struct args *p = (struct args*)arg; fp1 = fopen(p->src_file,"r"); if(fp1 == NULL){ fprintf(stderr,"fopen file %s fail:%s\n",p->src_file,strerror(errno)); exit(EXIT_FAILURE); } fp2 = fopen(p->des_file,"a"); if(fp2 == NULL){ fprintf(stderr,"fopen file %s fail:%s\n",p->des_file,strerror(errno)); exit(EXIT_FAILURE); } fseek(fp1,p->position,SEEK_SET); fseek(fp2,p->position,SEEK_SET); printf("p->position=%d,p->len=%d\n",p->position,p->len); read_len = p->len > 4096?4096:p->len; while(1){ if(count >= p->len){ break; } printf("read_len=%d\n",read_len); n = fread(buf,sizeof(buf[0]),read_len,fp1); if(n <= 0){ printf("fread over: %d\n",n); break; } printf("n=%d\n",n); ret = fwrite(buf,sizeof(buf[0]),n,fp2); if(ret <= 0){ printf("fwrite over\n"); break; } count += n; } printf("write %d bytes to des file\n",count); fclose(fp1); fclose(fp2); // pthread_mutex_unlock(&lock); } int main(int argc, const char *argv[]) { int ret; int len; int position; struct args args1,args2; pthread_t tid1,tid2; //pthread_mutex_init(&lock,NULL); if(argc < 3){ fprintf(stderr,"Usage: %s <filename> <filename>\n",argv[0]); exit(EXIT_FAILURE); } len = get_filelen(argv[1]); position = len / 2; init_args(&args1,argv[1],argv[2],0,position); init_args(&args2,argv[1],argv[2],position,len-position); fprintf(stdout,"src file length=%d\n",len); ret = pthread_create(&tid1,NULL,copy_file,&args1); if(ret != 0){ fprintf(stderr,"create pthread tid1 fail: %s\n",strerror(errno)); exit(EXIT_FAILURE); } ret = pthread_create(&tid2,NULL,copy_file,&args2); if(ret != 0){ fprintf(stderr,"create pthread tid2 fail: %s\n",strerror(errno)); exit(EXIT_FAILURE); } pthread_join(tid1,NULL); pthread_join(tid2,NULL); }