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);
}