linux进程与线程编程

2 篇文章 0 订阅
1 篇文章 0 订阅

Linux进程与线程编程


1. 创建进程

1.1进程说明

进程有生命周期,由fork()函数而创建,通过shedule()函数而执行,由wait()函数而等待,最后可强行终止运行进程,也可当完成任务后进程执行exit()函数自动退出。

​ 通过基本的Linux进程控制函数,由父进程创建子进程,并实现协同工作。创建两个进程,让子进程读取一个文件,父进程等待子进程读完文件后继续执行。

1.2 程序框架

​ fork()/exec()组合是典型的Linux新进程产生模式,通常先用fork()创建新进程,然后新进程通过调用exec()类执行自己的任务。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

#define COL 1024

int main(void){
	pid_t pc;									//创建进程组ID
	pc = fork();
	if (pc < 0){
		printf("error ocurred!\n");
	}else if (pc == 0){							//子进程创建成功
		printf("This is child process with pid of %d\n",getpid());
		char line[COL] = {0};
		FILE *file = fopen("/home/hcx/桌面/text/11.txt","r+");
		if (!file){
			printf("File opening failed\n");
		}else {
			printf("scan something to this file:");		//父进程
			while ((fscanf(file,"%s ",line)) != EOF)
			{
				printf("%s",line);
				sleep(1);						//睡眠1秒钟进行一次操作
			}
			printf("\n");
			fclose(file);
		}
		return 0;
	}
	else {										//父进程 
		wait(NULL);								//等待子进程
		printf("This is father process\n");
	}
	return 0;
}

​ 其中,用于子进程工作的文件11.txt内容是:

在这里插入图片描述

​ 用fork()创建进程时,子进程只是完全复制父进程的资源,子进程的执行独立于父进程,不改变父进程创建子进程之前定义的变量值;如果要控制父与子进程的执行顺序,必须由父进程使用函数wait(NULL)(返回任意终止状态的子进程)或waitpid()(等待特定的子进程)。

​ 而vfork()函数创建的子进程共享地址空间,即子进程运行在父进程的地址空间上,改变父进程创建子进程之前定义的变量值,创建子进程后,父进程会被阻塞,直到子进程执行exec()或exit()。

​ 在Linux中可通过使用exec()类函数实现进程对其他程序的引用,对系统而言,还是同一个进程,只不过运行另一个可执行程序。

1.3 运行结果

​ 当fork()调用成功后,父子进程完成各自的任务,但当父进程的工作告一段落,需要用到子进程的结果时,它就停下来调用wait(),直到子进程运行结束,然后利用子进程的结果继续执行,这样就解决了父子进程间的协同工作问题。

​ 运行结果如图:
在这里插入图片描述


2 线程共享进程中的数据

2.1 说明

​ 了解线程与进程之间的数据共享关系,创建一个线程,在线程中更改进程中的数据。

2.2 程序框架

​ 在Linux系统中,可通过函数clone()pthread_create()创建线程,两者区别在于clone()创建一个内核支持的用户线程,由内核调度;而pthread_create()创建一个线程库支持的用户线程,对内核不可见,由线程库调度。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

static int shdata = 4;

void *create(void *arg){
	printf("new pthread ...\n");
	printf("shared data = %d \n", shdata);
	return (void *)0;
}

int main (int argc, char *argv[]){
	int error;
	pthread_t tidp;
	error = pthread_create(&tidp, NULL, create, NULL);		//创建新线程
	/*
	当进程第1次调用pthread_create()创建一个线程时就会创建并启动管理线程
	*/
	if (error != 0){
		printf("pthread_create is not created...");
		return -1;
	}
	sleep(1);												//休眠1秒
	printf("prthread_create success...");
	return 0;
	
}

​ 注意:因为pthread库不是Linux系统的库,所以在进行编译的时候要加上-lpthread,否则编译通不过。如:

gcc -o test test.c -lpthread
2.3 运行结果

在这里插入图片描述


3 多线程实现单词统计工具

3.1 实验说明

​ 多线程实现单词统计工具。

3.2 程序框架

​ 允许线程使用互斥锁来修改临界资源,确保线程间的同步与协作。如果两个线程需要安全地共享一个公共计数器,需要把公共计数器加锁。线程需要访问称为互斥锁的变量,它可以使线程间很好地合作,避免对于资源的访问冲突。

#include <stdio.h>
#include <pthread.h>
#include <ctype.h>

pthread_mutex_t counter_clock = PTHREAD_MUTEX_INITIALIZER;
static int total_words = 0;

int main(int ac, char *av[]){
	void *count_words(void *);
	if (ac != 3){
		printf("Usage:%s file1.txt file2.txt\n",av[0]);
		return 0;
	}
	int t1, t2;
	pthread_t a_thread, b_thread;
	t1 = pthread_create(&a_thread, NULL, count_words, av[1]);	/* 以a_thread 和 b_thread 作为参数,创建两个线程t1和t2 */
	t2 = pthread_create(&b_thread, NULL, count_words, av[2]);
	if (t1 != 0 || t2 !=0){
		perror("Thread creation failed");
		return -1;
	}
	//分别让线程t1和t2进入等待态
	t1 = pthread_join(a_thread, NULL);	
	t2 = pthread_join(b_thread, NULL);
	if (t1 != 0 || t2 != 0){
		perror("Thread join failed");
		return -1;
	}
	//统计两个线程对应的文件的单词总数
	printf("The total words is:%d\n", total_words);

	return 0;
}

void *count_words(void *f){
	char *filename = (char *)f;
	FILE *fp;
	int c,prevc = '\0';

	if ((fp = fopen(filename, "r")) != NULL){
		while((c = getc(fp)) != EOF){
			if (!isalnum(c) && isalnum(prevc)){
				pthread_mutex_lock(&counter_clock);
				total_words++;
				pthread_mutex_unlock(&counter_clock);
			}
			prevc = c;
		}
		fclose(fp);
	}else {
		perror(filename);
	}
	return NULL;
}

​ 其中两个线程所用到的文件内容分别为:

​ file1文件:

在这里插入图片描述

​ file2文件:
在这里插入图片描述

3.运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值