2023/8/21 -- 进程线程

作业

1> 使用两个线程完成两个文件的拷贝,主线程拷贝前一半内容,子线程拷贝后一半内容,并且主线程要阻塞回收子线程资源

#include <myhead.h>

typedef struct{
	char *src_filename;
	char *dst_filename;
	int start_pos;
	int end_pos;
}copyval,*copyvalPtr;

void copyfile(char *src_file,char *dst_file,int start,int end){
	FILE *fp_src = fopen(src_file,"r");
	FILE *fp_dst = fopen(dst_file,"a");
	if(fp_src == NULL || fp_dst == NULL){
		perror("fopen error");
		return ;
	}
	fseek(fp_src,start,SEEK_SET);
	fseek(fp_dst,start,SEEK_SET);
	char buf[1] = {};
	while(ftell(fp_src) < end){
		fread(buf,1,1,fp_src);
		fwrite(buf,1,1,fp_dst);
	}
	fclose(fp_src);
	fclose(fp_dst);
	printf("拷贝成功\n");
}

void *task(void *arg){
	copyvalPtr val = (copyval *)arg;
	copyfile(val->src_filename,val->dst_filename,val->start_pos,val->end_pos);
	pthread_exit(EXIT_SUCCESS);
}

int main(int argc, const char *argv[])
{
	char src_file[] = "../1/01.c";
	char dst_file[] = "./aaa.txt";
	FILE *fp = fopen(src_file,"r");	
	if(fp == NULL){
		perror("fopen error");
		return -1;
	}
	fseek(fp,0,SEEK_END);
	int len = ftell(fp);
	int end = len;
	int mid = end / 2;
	copyval val = {src_file,dst_file,mid,end};
	pthread_t tid;
	int ret = pthread_create(&tid,NULL,task,&val);
	if(ret){
		printf("pthread_create error\n");
		return -1;
	}
	copyfile(src_file,dst_file,0,mid);
	pthread_join(tid,NULL);
	fclose(fp);
	return 0;
}

效果图:

 

2> 使用三个进程完成两个文件的拷贝,主线程拷贝前三分之一,子线程1拷贝中间三分之一,子线程2拷贝后三分之一,主线程要设置两个子线程为分离态

 

#include <myhead.h>

typedef struct{
	char *src_filename;
	char *dst_filename;
	int start_pos;
	int end_pos;
}copyval,*copyvalPtr;

void copyfile(char *src_file,char *dst_file,int start,int end){
	FILE *fp_src = fopen(src_file,"r");
	FILE *fp_dst = fopen(dst_file,"a");
	if(fp_src == NULL || fp_dst == NULL){
		perror("fopen error");
		return ;
	}
	fseek(fp_src,start,SEEK_SET);
	fseek(fp_dst,start,SEEK_SET);
	char buf[1] = {};
	while(ftell(fp_src) < end){
		fread(buf,1,1,fp_src);
		fwrite(buf,1,1,fp_dst);
	}
	fclose(fp_src);
	fclose(fp_dst);
	printf("拷贝成功\n");
}

void *task1(void *arg){
	sleep(3);
	copyvalPtr val = (copyval *)arg;
	copyfile(val->src_filename,val->dst_filename,val->start_pos,val->end_pos);
	pthread_exit(NULL);
}

void *task2(void *arg){
	sleep(5);
	copyvalPtr val = (copyval *)arg;
	copyfile(val->src_filename,val->dst_filename,val->start_pos,val->end_pos);
	pthread_exit(NULL);
}

int main(int argc, const char *argv[])
{
	char src_file[] = "../1/01.c";
	char dst_file[] = "./bbb.txt";
	FILE *fp = fopen(src_file,"r");	
	if(fp == NULL){
		perror("fopen error");
		return -1;
	}
	fseek(fp,0,SEEK_END);
	int len = ftell(fp);
	int end = len;
	int fir_pos = end / 3;
	int sec_pos = end / 3 * 2;
	copyval val1 = {src_file,dst_file,fir_pos,sec_pos};
	copyval val2 = {src_file,dst_file,sec_pos,end};
	pthread_t tid1,tid2;
	int ret1 = pthread_create(&tid1,NULL,task1,&val1);
	int ret2 = pthread_create(&tid2,NULL,task2,&val2);
	if(ret1 != 0 || ret2 != 0){
		printf("pthread_create error\n");
		return -1;
	}
	pthread_detach(tid1);
	pthread_detach(tid2);
	copyfile(src_file,dst_file,0,fir_pos);
	fclose(fp);
	while(1);
	return 0;
}

效果图:

 

 

三、多线程

3.1 多线程概念

  • 多线程(LWP轻量版的进程):线程是更小粒度的单元
  • 线程是任务调度的最小单位,进程是资源分配的最小单位
  • 线程几乎不占进程的资源,只是占用了很小的有关线程体的相关资源,8k左右
  • 多个线程共享进程的资源,所以,线程没有进程安全
  • 在一个进程中,至少由一个线程(主线程)
  • 线程的切换所消耗的资源比进程切换消耗的少
  • 线程所在的进程结束后,该进程中的所有线程全部结束
  • 进程中的多个线程的调度方式:时间片轮询,上下文切换,没有先后顺序

3.2 线程的创建(pthread_creat)

       #include <pthread.h>

       int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
 void *(*start_routine) (void *), void *arg);    //void * (*ptr)(void * , int)
功能:创建一个线程
参数1:线程号(通过地址返回)
参数2:线程的属性,一般写NULL
参数3:线程体函数,是一个函数指针,参数和返回值都为void*类型
参数4:万能指针,是线程体函数的参数
返回值:成功返回0,失败返回错误码,并且线程号不存在               

       Compile and link with -pthread.          //编译时,需要链接pthread库

练习:主线程向子线程传递两个数据,子线程输出这两个数的和

#include<myhead.h>

//定义数据结构体
struct Data
{
    int value_1;
    int value_2;
};

//定义线程体函数
void *task1(void *arg)
{
    //将数据进行解压出来
    struct Data data = * (struct Data*)arg;

    printf("sum = %d\n", data.value_1+data.value_2);
}



int main(int argc, const char *argv[])
{
    int num = 5;
    int key = 3;

    //定义数据结构体变量
    struct Data data = {num, key};

    //定义子线程
    pthread_t tid;
    //创建线程
    if(pthread_create(&tid, NULL, task1, &data))
    {
        printf("线程创建失败\n");
        return -1;
    }

    while(1);
    
    return 0;
}

3.3 线程号的获取(pthread_self)

       #include <pthread.h>

       pthread_t pthread_self(void);
功能:获取当前线程的线程号
参数:无
返回值:总是成功,返回当前线程的线程号

3.4 线程退出函数(pthread_exit)

1> 不能使用exit或者_exit退出线程,如果在线程体中使用这两个函数,则会直接结束整个进程

2> 可以使用pthread_exit退出某个线程

       #include <pthread.h>

       void pthread_exit(void *retval);
功能:退出当前线程
参数:退出线程时的状态,一般为NULL
返回值:无

3.5 线程的资源回收(pthread_join)

       #include <pthread.h>

       int pthread_join(pthread_t thread, void **retval);
功能:阻塞等待线程的结束并为线程收尸
参数1:线程id
参数2:线程退出时的状态,一般为NULL
返回值:成功返回0,失败返回错误码

 

 

3.6 向线程发信号(pthread_cancel)

       #include <pthread.h>

       int pthread_cancel(pthread_t thread);
功能:向指定的线程发送取消信号,让该线程结束
参数:要取消的线程号
返回值:成功返回0,失败返回非0的错误码

       #include <pthread.h>

       int pthread_setcancelstate(int state, int *oldstate);
功能:设置线程取消的状态
参数1:要更改的线程状态
        PTHREAD_CANCEL_ENABLE:可以接收取消请求(默认)


       PTHREAD_CANCEL_DISABLE:不接收取消请求
参数2:旧的状态,一般写NULL
返回值:成功返回0,失败返回非0的错误码
              

3.7 线程分离(pthread_detach)

       #include <pthread.h>

       int pthread_detach(pthread_t thread);
功能:将指定的某个线程设置成分离态,设置成分离态的线程,当其结束时,系统会自动回收其资源,无需使用pthread_join来回收
参数:要设置分离态的线程号
返回值:成功返回0,失败返回错误码

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值