【Ubuntu】进程与线程编程实验
创始人
2024-03-01 15:05:26
0

文章目录

  • 进程与线程
    • 实验一:创建进程
      • 基础版:创建父子线程 fork
      • 基础版:父子线程交替运行
      • 基础版:创建进程 文件写入
      • 练习版:创建线程 子读父阻塞
    • 实验二:线程共享进程中的数据
    • 实验三:多线程实现单词统计工具


进程与线程

实验一:创建进程

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

注意:

  • fork创建的新进程被称为子进程,该函数被调用一次,但返回两次。两次返回的区别是:在子进程中的返回值是0,而在父进程中的返回值则是新进程的进程ID。

  • 创建子进程,父进程哪个先运行根据系统调度且赋值父进程的内存空间。

  • vfork创建子进程,但子进程先运行且不复制父进程的内存空间

基础版:创建父子线程 fork

#include 
#include 
#include 
#include 
#include int main(void){printf("pid:%d\n",getpid());pid_t pid;pid = fork(); // 创建子进程// 在fork之后会运行两个进程(父进程、子进程)if(pid <0){perror("fork error");} else if(pid>0){// 父进程(在父进程中fork返回的是子进程的pid)printf("I am parent process pid is %d,ppid is %d,fork return is %d\n",getpid(),getppid(),pid);} else { // 子进程(在子进程中fork返回的是0)    printf("I am child  process pid is %d,ppid is %d,fork return is %d\n",getpid(),getppid(),pid); }printf("pid:%d\n",getpid());sleep(1); // 睡眠return 0;
}

编译源文件:

root@ubuntu:/home/course/linux# gcc -o /home/course/linux/out/createThread /home/course/linux/createThread.c
  • -c 表示只编译(compile)源文件但不链接,会把.c或.cc的c源程序编译成目标文件,一般是.o文件。
  • -o 用于指定输出(out)文件名。不用-o的话,一般会在当前文件夹下生成默认的a.out文件作为可执行程序。

image-20221129143809506

root@ubuntu:/home/course/linux/# out/createThread  # 直接运行

image-20221129144124561

可以看到:

  • 父进程(在父进程中fork返回的是子进程的pid)

  • 子进程(在子进程中fork返回的是0)

image-20221129144641728

返回顶部


基础版:父子线程交替运行

使用sleep()函数,实现线程的睡眠,每个进程运行后休眠一段时间,这时按照cpu的资源调度,使得其他进程运行。(若休眠时间短则会出现二次调用的情况)

#include 
#include 
#include 
#include 
#include int main(void){printf("pid:%d\n",getpid());pid_t pid;pid = fork(); // 创建子进程// 在fork之后会运行两个进程(父进程、子进程)if(pid <0){perror("fork error");} else if(pid>0){for(int i=0;i<10;i++){// 父进程(在父进程中fork返回的是子进程的pid)printf("I am parent process pid is %d\n",getpid());sleep(1);}} else { for(int i=0;i<10;i++){// 子进程(在子进程中fork返回的是0)    printf("I am child  process pid is %d\n",getpid()); sleep(1);}}return 0;
}

编译运行:

root@ubuntu:/home/course/linux# vi createThread1.c
root@ubuntu:/home/course/linux# gcc -o /home/course/linux/out/createThread1 /home/course/linux/createThread1.c

image-20221129150054672

返回顶部


基础版:创建进程 文件写入

父进程使用两种IO的形式进行文件的写入,默认当前路径下创建文件。注意区分缓存的概念以及文件的内容输出。

#include 
#include 
#include 
#include 
#include int main(void){printf("pid:%d\n",getpid());/*父进程调用写文件*/FILE *fp =fopen("s.txt","w");int fd = open("s_fd.txt",O_WRONLY|O_CREAT|O_TRUNC,S_IRWXU|S_IRWXG);char *s = "hello world!";ssize_t size = strlen(s)*sizeof(char);// 标准IO函数 - 带缓存 - 全缓存fprintf(fp,"s:%s,pid:%d",s,getpid());// 内核提供的IO系统 - 不带缓存write(fd,s,size);pid_t pid;pid = fork(); // 创建子进程// 在fork之后会运行两个进程(父进程、子进程)if(pid <0){perror("fork error");} else if(pid>0){for(int i=0;i<10;i++){// 父进程(在父进程中fork返回的是子进程的pid)printf("I am parent process pid is %d\n",getpid());sleep(1);}} else { for(int i=0;i<10;i++){// 子进程(在子进程中fork返回的是0)    printf("I am child  process pid is %d\n",getpid()); sleep(1);}}// 父子进程都要执行 - 写入各自缓存fprintf(fp,"pid:%d",getpid());return 0;
}

可以看到编译正常运行;

image-20221129161536294

并且在目录下新生成了 s_fd.txt、s.txt 文件,当我们查看文件内容的时候,会发现两个文件中的内容有偏差:

image-20221129161812264

使用内核提供的IO系统 - 不带缓存,是直接将内容写入,而标准IO函数 - 带缓存,写的内容是:fprintf(fp,"s:%s,pid:%d",s,getpid());,并且在最后的时候父子进程都要执行一次标准的IO,將各自的缓存内容写入到文件中去,所以会重复内容一次。

image-20221129163037732

返回顶部


练习版:创建线程 子读父阻塞

实验说明:

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

解决方案:

  • 进程协同工作就是要协调好两个或两个以上的进程,使之安排好先后次序并依次执行,可以用wait()或者waitpid()函数来实现这一点。当只需要等待任一子进程运行结束时,可在父进程中调用wait()函数。若需要等待某一特定子进程的运行结果时,需调用waitpid()函数,它是非阻塞型函数。
image-20221129164336225
#include 
#include 
#include 
#include 
#include 
#include
#include#define COLMAX 1024 //每一个字符串的最大长度(列)
#define ROWMAX 64   //字符串最大个数(行)/*
本代码实现用子进程打开同目录下的s_fd.txt文件
并且父进程输出内容
*/int main(void) {int p_id = -1;//子进程创建失败if ((p_id = fork()) == -1) {printf("Process_1 Create Error\n");} else if (p_id == 0) { //子进程部分printf("%d Process Start Work\n", getpid());char text[ROWMAX][COLMAX] = {0};FILE *fp = fopen("s_fd.txt", "r+");//打开文件if (fp == NULL) { //打开文件失败printf("Fail to open file!\n");} else {int i = 0;while ((fscanf(fp, "%s", text[i])) != EOF) {printf("%s\n", text[i]);i++;sleep(1);   //等待1s方便查看输出}}fclose(fp);exit(0);}//父进程部分waitpid(p_id, NULL, 0);//阻塞等待printf("%d process is end\n", p_id);return 0;
}
rse/linux# vi createThread3.c
root@ubuntu:/home/course/linux# gcc -o /home/course/linux/out/createThread3 /home/course/linux/createThread3.c 
root@ubuntu:/home/course/linux# out/createThread3

运行结果:

image-20221129171216972

返回顶部


实验二:线程共享进程中的数据

实验说明:

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

解决方案:

  • 在进程中定义共享数据,在线程中直接引用并输出该数据。
image-20221129171410972
#include 
#include 
#include 
#include 
#include 
#include
#includestatic int sharedata=4; // 共享数据void *create(void *arg){printf("new pthread...\n");printf("sharedata data = %d \n",sharedata);sharedata = 3;return (void *)(0);
}int main(void){pthread_t mythread ;sharedata=5; // 修改变量值int error = 0;error = pthread_create(&mythread,NULL,create,NULL);if(error){printf("pthread_create is not created...\n");return -1;}sleep(1);printf("pthread_create is ok...\n");printf("And shared data = %d\n \n",sharedata);return 0;
}
root@ubuntu:/home/course/linux# vi createThread4.c
root@ubuntu:/home/course/linux# gcc -o /home/course/linux/out/createThread4 /home/course/linux/createThread4.c -l pthread
root@ubuntu:/home/course/linux# out/createThread4

运行结果:

在这里插入图片描述

如有报错,参见:https://blog.csdn.net/u014470361/article/details/83214911

返回顶部


实验三:多线程实现单词统计工具

实验说明:

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

解决方案:

  • 区分单词原则:
    • 凡是一个非字母或数字的字符跟在字母或数字的后面,那么这个字母或数字就是单词的结尾。
    • 允许线程使用互斥锁来修改临界资源,确保线程间的同步与协作。
    • 如果两个线程需要安全地共享一个公共计数器,需要把公共计数器加锁。线程需要访问称为互斥锁的变量,它可以使线程间很好地合作,避免对于资源的访问冲突。

image-20221129172729652

#include 
#include 
#include 
#include 
#include pthread_mutex_t counter_clock=PTHREAD_MUTEX_INITIALIZER;int main(int ac,char *av[]){void *count_words(void *);if(ac!=3){printf("Usage:%s file1 file2\n",av[0]);exit(1);}/*分別以av[1]、av[2]作为参数,创建两个线程t1、t2,线程t1、t2进入等待状态,输出统计的单词总数*/pthread_t tidp1,tidp2;int error1,error2;error1=pthread_create(&tidp1,NULL,count_words,av[1]);error2=pthread_create(&tidp2,NULL,count_words,av[2]);pthread_join(tidp1,NULL);pthread_join(tidp2,NULL);return 0;
}void *count_words(void *f){char *filename=(char *)f;FILE *fp;int c,prevc='\0';int total_words=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);printf("total_words=%d\n",total_words);}else{perror(filename);}return NULL;
}

创建两个包含英文单词的txt文件:

image-20221129173438945

root@ubuntu:/home/course/linux# vi createThread5.c
root@ubuntu:/home/course/linux# gcc -o /home/course/linux/out/createThread5 /home/course/linux/createThread5.c -l pthread
root@ubuntu:/home/course/linux# ./out/createThread5 ./a.txt ./b.txt 
total_words=5
total_words=3

运行结果:

image-20221129173907407

返回顶部


相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...