Linux系统编程线程函数,多线程的简单应用

多线程

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

线程的创建(pthread_creat

  • 功能

    • 创建一个线程
  • 原型

    •   #include <pthread.h>
        int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
      
  • 函数参数

    • pthread_t *thread:线程号(通过地址返回)
    • const pthread_attr_t *attr:线程的属性,一般写NULL
    • void*(*start_routine) (void *):线程体函数,是一个函数指针,参数和返回值都为void*类型
    • void *arg:万能指针,是线程体函数的参数
  • 返回值

    • 成功:返回0
    • 失败:返回错误码,并且线程号不存在

线程号的获取(pthread_self

  • 功能

    • 获取当前线程的线程号
  • 原型

    •   #include <pthread.h>
         pthread_t pthread_self(void);
      
  • 参数:无

  • 返回值

    • 总是成功,返回当前线程的线程号

线程退出函数(pthread_exit

  • 功能

    • 退出线程
  • 原型

    •   #include <pthread.h>
        void pthread_exit(void *retval);
      
  • 参数

    • void *retval:退出线程时的状态值,一般为NULL
  • 返回值:无

线程回收函数(pthread_join

  • 功能

    • 阻塞函数,阻塞等待的指定线程退出,并回收资源
  • 原型

    •   #include <pthread.h>
        int pthread_join(pthread_t thread, void **retval);
      
  • 参数

    • pthread_t thread:指定要回收的线程,填对应的tid号
    • void **retval:一般为NULL
  • 返回值

    • 成功:返回0
    • 失败:返回error_number

向线程发信号(pthread_cancel

  • 功能

    • 向指定的线程发送取消信号,让该线程结束
  • 原型

    •   #include <pthread.h>
        int pthread_cancel(pthread_t thread);
      
  • 参数

    • pthread_t thread:指定要请求的线程tid号
  • 返回值

    • 成功:返回0
    • 失败:返回error_number

设置线程取消状态(int pthread_setcancelstate

  • 功能

    • 设置线程取消的状态
  • 原型

    •   #include <pthread.h>
        int pthread_setcancelstate(int state, int *oldstate);
      
  • 参数

    • int state:要更改的线程状态
      • PTHREAD_CANCEL_ENABLE:可以接受取消请求(默认)
      • PTHREAD_CANCEL_DISABLE:不接受取消请求
    • int *oldstate:旧的状态,一般写NULL
  • 返回值

    • 成功:返回0
    • 失败:返回非0的错误码

分离线程(pthread_detach

  • 功能

    • 将指定的某个线程设置成分离态,然后设置成分离态的线程,当其结束时,系统会自动回收其资源,无需使用pthread_join来回收
  • 原型

    •   #include <pthread.h>
        int pthread_detach(pthread_t thread);
      
  • 参数

    • pthread_t thread:指定要分离的线程(tid
  • 返回值

    • 成功:返回0
    • 失败:返回错误码

利用多线程实现文件的拷贝

//两个线程实现拷贝
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
typedef struct file
{
	char *str1;
	char *str2;
} File_name_t;


void* task1(void *arg)
{
	//创建两个文件描述符
	int fd_r, fd_w;
	//只读打开文件
	fd_r = open((*(File_name_t *)arg).str1, O_RDONLY);
	if(fd_r < 0)
	{
		perror("open error");
		pthread_exit(NULL);
	}
	//只写打开文件
	fd_w = open((*(File_name_t *)arg).str2, O_WRONLY);
	if(fd_w < 0)
	{
		perror("open error");
		close(fd_r);
		pthread_exit(NULL);
	}

	//计算文件大小
	off_t file_size = lseek(fd_r, 0, SEEK_END);

	//将读写光标移动到文件开头
	lseek(fd_r, 0, SEEK_SET);
	lseek(fd_w, 0, SEEK_SET);

	//以每次一个字节进行数据拷贝
	char c = 0;
	for(int i = 0; i < file_size/2; i++)
	{
		read(fd_r, &c, 1);
		write(fd_w, &c, 1);
	}

	//关闭文件,退出线程
	puts("前半部分拷贝完毕");
	close(fd_r);
	close(fd_w);

	pthread_exit(NULL);

}

void* task2(void *arg)
{
	//创建两个文件描述符
	int fd_r, fd_w;
	//只读打开文件
	fd_r = open((*(File_name_t*)arg).str1, O_RDONLY);
	if(fd_r < 0)
	{
		perror("open error");
		pthread_exit(NULL);
	}
	//只写打开文件
	fd_w = open((*(File_name_t*)arg).str2, O_WRONLY);
	if(fd_w < 0)
	{
		perror("open error");
		close(fd_r);
		pthread_exit(NULL);
	}

	//计算文件大小
	off_t file_size = lseek(fd_r, 0, SEEK_END);

	//将读写光标移动到文件中间
	lseek(fd_r, file_size - file_size/2, SEEK_SET);
	lseek(fd_w, file_size - file_size/2, SEEK_SET);

	//以每次一个字节进行数据拷贝
	char c = 0;
	for(int i = file_size - file_size/2; i < file_size; i++)
	{
		read(fd_r, &c, 1);
		write(fd_w, &c, 1);
	}

	//关闭文件,退出线程
	puts("后半部分拷贝完毕");
	close(fd_r);
	close(fd_w);

	pthread_exit(NULL);

}

int main(int argc, char *argv[])
{

	int fd_w = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
	if(fd_w < 0)
	{
		perror("open error");
		return -1;
	}
	close(fd_w);

	File_name_t file_name;
	file_name.str1 = argv[1];
	file_name.str2 = argv[2];

	pthread_t tid1, tid2;

	if(pthread_create(&tid1, NULL, task1, &file_name) != 0)
	{
		puts("tid1 pthread_creat error");
		return -1;
	}
	if(pthread_create(&tid2, NULL, task2, &file_name) != 0)
	{
		puts("tid2 pthread_creat error");
		return -1;
	}

	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);


    return 0;
}


//三线程拷贝
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>

//定义文件结构体
typedef struct file
{
	char *strfile;
	char *dstfile;
	off_t file_size;
	off_t file_start;
} File_t;

/*
函数功能:算出文件的大小,若目标文件不存在创建该文件
函数参数:拷贝源文件,拷贝目标文件
返回值:拷贝文件的大小
*/
int get_file_size(const char* strfile, const char* dstfile)
{
	//定义返回值和两个文件描述符
	int ret = 0;
	int fd_w, fd_r;
	//以只读的方式打开文件
	fd_r = open(strfile, O_RDONLY);
	if(fd_r < 0)
	{
		perror("strfile open error");
		return -1;
	}

	//以只写的形式打开文件
	fd_w = open(dstfile, O_WRONLY | O_CREAT | O_TRUNC, 0664);
	if(fd_w < 0)
	{
		perror("dstfile open error");
		return -1;
	}

	//计算文件长度
	ret = lseek(fd_r, 0, SEEK_END);

	//关闭文件
	close(fd_w);
	close(fd_r);

	return ret;
}

/*
函数功能:拷贝文件 
函数参数:拷贝源文件,拷贝目标文件,读写文件光标起始位置,拷贝文件的大小
返回值:无
*/
void copy_file(const char* strfile, const char* dstfile, int file_start, int file_size)
{
	//定义两个文件描述符
	int fd_r, fd_w;
	//以只读的方式打开源文件
	fd_r = open(strfile, O_RDONLY);
	if(fd_r < 0)
	{
		perror("strfile open error");
		return;
	}

	//以只写的方式打开目标文件
	fd_w = open(dstfile, O_WRONLY);
	if(fd_w < 0)
	{
		perror("dstfile open error");
		return;
	}

	//定位光标位置
	lseek(fd_r, file_start, SEEK_SET);
	lseek(fd_w, file_start, SEEK_SET);

	//进行数据拷贝
	char c = 0;
	int ret = 0;
	while(1)
	{
		if((ret = read(fd_r, &c, 1)) == 0)
			break;
		write(fd_w, &c, 1);
	}
	puts("拷贝成功");
}

//三个线程各自拷贝文件的三分之一大小
void *task1(void *arg)
{
	File_t f = *(File_t*)arg;
	copy_file(f.strfile, f.dstfile, f.file_start, f.file_size);
	pthread_exit(NULL);
}

void *task2(void *arg)
{
	File_t f = *(File_t*)arg;
	copy_file(f.strfile, f.dstfile, f.file_start, f.file_size);
	pthread_exit(NULL);
}

void *task3(void *arg)
{
	File_t f = *(File_t*)arg;
	copy_file(f.strfile, f.dstfile, f.file_start, f.file_size);
	pthread_exit(NULL);
}



int main(int argc, char *argv[])
{
	//判断文件传入数量
	if(argc != 3)
	{
		printf("input file error\n");
		printf("usage: ./a.out srcfile dstfile\n");
		return -1;
	}

	//定义三个线程tid
	pthread_t tid1, tid2, tid3;

	//对文件结构体进行赋值
	File_t File;
	File.strfile = argv[1];
	File.dstfile = argv[2];
	//task1线程光标的开始位置
	File.file_start = 0;
	File.file_size = get_file_size(argv[1], argv[2]);

	if(pthread_create(&tid1, NULL, task1, &File) != 0)
	{
		puts("tid1 pthread_create error");
		return -1;
	}

	//task2线程光标的开始位置	
	File.file_start = get_file_size(argv[1], argv[2])/3;

	if(pthread_create(&tid2, NULL, task2, &File) != 0)
	{
		puts("tid2 pthread_create error");
		return -1;
	}

	//task3线程光标的开始位置
	File.file_start = File.file_size - (File.file_size - get_file_size(argv[1], argv[2])/3);

	if(pthread_create(&tid3, NULL, task3, &File) != 0)
	{
		puts("tid3 pthread_create error");
		return -1;
	}

	//线程资源的回收
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	pthread_join(tid3, NULL);
	
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值