关于多进程与多进程需要注意的基础知识点

进程

什么是进程

        程序的每次执行就会创建一个进程,进程就是一个正在执行的任务,同时随着程序的结束而结束。进程是分配资源的最小单位(0~3G)

        进程运行的状态:ps -ajx 查询 

                D:不可中断的休眠态(信号)        R:运行态        S:可中断的休眠态(信号)

                T:停止状态          X:死亡状态        Z:僵尸态

        附加状态:

                <:高优先级        N:低优先级        L:在内存区锁定

                s:会话组组长        l:进程中包含多线程        +:前台进程

多进程

        子进程的创建是通过拷贝父进程完成的,子进程的所有资源都来自与父进程。当拷贝生成子进程后,父子进程执行的时候相互独立,执行没有先后顺序,时间片轮询

#include <head.h>

int main(int argc, const char *argv[])
{
	//创建进程
	pid_t pid;
	//拷贝进程
	pid = fork();
	if(pid == -1){    //拷贝失败(子进程创建失败)
		printf("fork error\n");
		return -1;
	}else if(pid == 0){		//子进程创建成功
		while(1){
			sleep(1);
			printf("子进程1\n");
		}
	}else{		//父进程
		while(1){
			sleep(1);
			printf("父进程\n");
		}
	}

	return 0;
}

执行结果:

 进程退出 exit/_exit函数

区别:

        exit函数:是一个库函数,在退出进程是刷新缓存区

        _exit函数:是一个系统调用,在退出时不会刷新缓存区

 进程资源回收 wait/waitpid函数

wait(NULL) == waitpid(-1, NULL, 0)        wait(&status) == waitpid(-1, &status, 0)

区别:

        wait:其在父进程中使用,会阻塞等待子进程结束,NULL表示不关心子进程返回值

        waitpid:-1 表示回收任意子进程,也可以填子进程号,表示回收指定子进程

                        0 表示阻塞等待,也可以填 WNOHANG 非阻塞等待

#include <head.h>

int main(int argc, const char *argv[])
{
	pid_t pid1, pid2;
	if((pid1 = fork()) == 0){
		sleep(3);
		printf("111111\n");
		exit(0);
		printf("222222\n");
	}else{
		if((pid2 = fork()) == 0){
			sleep(1);
			printf("333333\n");
			exit(0);
		}else{
			wait(NULL);		//阻塞等待子进程结束
			wait(NULL);
			printf("444444\n");
			printf("555555");
			_exit(0);
		}
	}

	return 0;
}

执行结果:

多线程

        线程是轻量级的进程,线程是调度的最小单位,线程不会分配内存空间,其共享当前进程的内存空间(0~3G),多线程没有多进程安全,但多线程的效率高。执行没有先后顺序,时间片轮询,线程间传参,可以直接使用全局变量

        线程需要第三方库的安装:(在线安装)编译的时候加 -lpthread

        sudo apt-get install manpages-posix manpages-posix-dev 

多线程拷贝文件:

#include <head.h>

typedef struct{
	const char* src;
	const char* dest;
	int start;
	int length;
}file_t;

int get_length(const char* srcfile, const char* destfile){
	int sfd, dfd, length;
	if((sfd = open(srcfile, O_RDONLY)) == -1){
		perror("open srcfile error");
		return -1;
	}
	if((dfd = open(destfile, O_RDWR|O_TRUNC|O_CREAT,0666)) == -1){
		perror("open destfile error");
		return -1;
	}
	length = lseek(sfd, 0, SEEK_END);
	close(sfd);
	close(dfd);
	return length;
}

int copy_file(const char* src, const char* dest, int start, int length){
	int sfd, dfd, ret, count = 0;
	char buf[128] = {0};
	if((sfd = open(src, O_RDONLY)) == -1){
		perror("open srcfile error");
		return -1;
	}
	if((dfd = open(dest, O_RDWR)) == -1){
		perror("open srcfile error");
		return -1;
	}
	//定位源文件和目标文件的光标位置
	lseek(sfd, start, SEEK_SET);
	lseek(dfd, start, SEEK_SET);

	while(1){
		ret = read(sfd, buf, sizeof(buf));
		if(ret <= 0){	//表示读取到结尾
			break;
		}
		count += ret;
		if(count >= length){	//超出读取范围
			write(dfd, buf, length-(count-ret));
			break;
		}
		write(dfd, buf, ret);
	}
	close(sfd);
	close(dfd);
	return 0;
}

void *task(void *arg){
	file_t *f = (file_t*)arg;
	copy_file(f->src, f->dest, f->start, f->length);
}

int main(int argc, const char *argv[])
{
	pthread_t tid1, tid2;
	int length = 0;
	if(argc != 3){
		printf("input error, try again\n");
		printf("usage: ./a.out filename1 filename2\n");
		return -1;
	}
	//获取源文件的长度,并创建目标文件
	length = get_length(argv[1], argv[2]);
	if(length < 0){
		printf("file init error");
		return -1;
	}
	file_t f[] = {
		[0] = {
			.src = argv[1],
			.dest = argv[2],
			.start = 0,
			.length = length/2
		},
		[1] = {
			.src = argv[1],
			.dest = argv[2],
			.start = length/2,
			.length = length - (length/2)
		}
	};
	//两个线程同时读取,tid1 读取上半部分 tid2 读取下半部分
	if(pthread_create(&tid1, NULL, task, (void*)&f[0])){
		perror("create thread 1 error");
		return -1;
	}
	if(pthread_create(&tid2, NULL, task, (void*)&f[1])){
		perror("create thread 2 error");
		return -1;
	}
	//回收线程资源
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);

	return 0;
}

多线程函数

pthread_exit:退出当前线程(pthread_join()接收)

pthread_join:阻塞回收结合态的线程资源

pthread_cancle:一个线程向另一个线程发送结束信号

pthread_detach:将线程标记为分离态,在线程结束后资源自动回收

pthread_self:获取自己的线程ID

#include <head.h>

pthread_t tid1, tid2, ptid;

void *task1(void *arg){
    //不可被取消
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
    while(1){
        sleep(1);
        printf("线程1\n");
    }
    printf("111111\n");
}
void *task2(void *arg){
    pthread_detach(pthread_self());
    printf("线程2\n");
    sleep(5);
    pthread_cancel(tid1);
    pthread_cancel(ptid);
}

int main(int argc, const char *argv[])
{
    //可以被取消
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    if(pthread_create(&tid1, NULL, task1, NULL)){
        perror("create thread 1 error");
		return -1;
    }
    if(pthread_create(&tid2, NULL, task2, NULL)){
        perror("create thread 2 error");
		return -1;
    }
    ptid = pthread_self();
    printf("tid1 = %ld tid2 = %ld\n", tid1, tid2);
    while(1){
        sleep(1);
        printf("222222\n");
    }

    return 0;
}

执行结果:

 线程的互斥

在多线程中,如果多线程同时在访问同一个全局变量,就可能出现多个线程在获取变量值时候获取的是同一个值,此时在线程中操作这个变量就会出现不同步的效果。

互斥锁

1 >> 定义互斥锁:pthread_mutex_t mutex

2 >> 初始化互斥锁:pthread_mutex_init()

3 >> 上锁:pthread_mutex_lock()(没有获取锁,会阻塞等待)

                        pthread_mutex_trylock()(没有锁获取,立即返回)

4 >>  解锁:pthread_mutex_unlock()

5 >>  销毁锁:pthread_mutex_destroy()

#include <head.h>

pthread_mutex_t mutex;
int money = 10000;

void *task1(void *arg){
    printf("线程1\n");
    while(1){
        sleep(1);
        pthread_mutex_lock(&mutex);
        money -= 500;
        if(money > 0){
            printf("张三取了500,还剩<%d>\n", money);
        }else{
            printf("没钱了,张三取钱失败\n");
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }
        pthread_mutex_unlock(&mutex);
    }
}
void *task2(void *arg){
    printf("线程2\n");
    while(1){
        sleep(1);
        pthread_mutex_lock(&mutex);
        money -= 1000;
        if(money > 0){
            printf("李四取了1000,还剩<%d>\n", money);
        }else{
            printf("没钱了,李四取钱失败\n");
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }
        pthread_mutex_unlock(&mutex);
    }
}

int main(int argc, const char *argv[])
{
    pthread_t tid1, tid2;
    pthread_mutex_init(&mutex, NULL);
    if(pthread_create(&tid1, NULL, task1, NULL)){
        perror("create thread 1 error");
		return -1;
    }
    if(pthread_create(&tid2, NULL, task2, NULL)){
        perror("create thread 2 error");
		return -1;
    }
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);

    pthread_mutex_destroy(&mutex);

    return 0;
}

执行结果:

当线程为分离态时需注意:

#include <head.h>

int money = 10000;
pthread_mutex_t mutex;
pthread_t tid1, tid2;

void *task(void *arg){
	printf("1111\n");
	pthread_detach(pthread_self());
	while(1){
		sleep(1);
		pthread_mutex_lock(&mutex);
		money -= 100;
		if(money > 0){
			printf("取 100, 剩余 %d\n", money);
		}else{
			printf("没钱了,1111\n");
			pthread_mutex_unlock(&mutex);
			pthread_exit(NULL);
		}
		pthread_mutex_unlock(&mutex);
	}
}

void *task1(void *arg){
	printf("2222\n");
	pthread_detach(pthread_self());
	while(1){
		sleep(1);
		pthread_mutex_lock(&mutex);
		money -= 350;
		if(money > 0){
			printf("取 350, 剩余 %d\n", money);
		}else{
			printf("没钱了,2222\n");
			pthread_mutex_unlock(&mutex);
			pthread_exit(NULL);
		}
		pthread_mutex_unlock(&mutex);
	}
}

int main(int argc, const char *argv[])
{
	pthread_mutex_init(&mutex, NULL);

	if(pthread_create(&tid1, NULL, task, NULL))
		PRINT_ERR("create error");
	if(pthread_create(&tid2, NULL, task1, NULL))
		PRINT_ERR("create error");
	printf("-------\n");
	while(1);	//当线程设为分离态时,需注意主程序进程
	
	pthread_mutex_destroy(&mutex);


	return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值