该实验所有代码都是在ubuntu20.4系统下运行的
一、实验目的
2理解Linux下形成新进程的方式(系统调用—fork函数);
3把握怎么启动另一程序的执行;
4理解Linux下线程的结构;
5理解Linux下形成新线程的技巧;
6理解Linux系统下多进程与多线程的区别
7了解哪些是管线
8熟悉UNIX/LINUX支持的管线通讯方法
10Gdb调试工具的熟练使用
二实验环境
Ubuntulinux
三实验内容
1借助fork函数创建新进程,并按照fork函数的返回值,判定自己是处于父进程还是子进程中;
2在新创建的子进程中,使用exec类的函数启动另一程序的执行;剖析多进程时系统的运行状态和输出结果;
3借助最常用的三个函数pthread_create,pthread_join和pthread_exit编撰了一个最简单的多线程程序。理解多线程的运行和输出情况;
4借助讯号量机制控制多线程的运行次序,并实现多线程中数据的共享;
5剖析Linux系统下多进程与多线程中的区别。
6编撰程序实现进程的管线通讯。用系统调用pipe()构建一管线,二个子进程P1和P2分别向管线各写一句话:
Child1issendingamessage!
Child2issendingamessage!
父进程从管线中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。
7编撰一个HelloWorld内核模块,并进行装载和卸载操作
实验中用到的系统调用函数:
fork()、exec()、pthread_create()、pthread_join()、read()、write()、lockf()
实验步骤
1借助fork函数编撰一个简单的多进程程序,用ps命令查看系统中进程的运行状况,并剖析输出结果。
2在里面的多进程程序中借助exec函数,启动另一个程序的执行。用ps命令显示本机运行的所有进程的详尽列表,并剖析列表中不同进程的显存占用情况。
3编撰一个最简单的多线程程序。理解多线程的运行和输出情况;
4借助讯号量机制控制多线程的运行次序嵌入式linux 培训,剖析多线程中数据的共享情况;
5剖析Linux系统下多进程与多线程中的区别。
6编撰程序实现进程的管线通讯。用系统调用pipe()构建一管线,二个子进程P1和P2分别向管线各写一句话:
Child1issendingamessage!
Child2issendingamessage!
父进程从管线中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。
7编撰一个HelloWorld内核模块,并进行装载和卸载操作
8调试剖析结果,给出总结感受。
五、实验结果及剖析
1、
在代码中添加sleep()目的是让进程不这么快结束掉,不然一下子就执行完了,倘若此时再输入ps命令的话就看不到兄妹进程信息了。
首先使用gcc命令编译代码,之后一个终端执行./fork命令,另一个终端输入ps-ef|grepfork命令查看进程信息。
其中命令ps-ef,参数-e表示显示系统内所有进程信息,参数-f表示使用完整的格式显示进程信息,倘若不使用-f参数的话,就不能看见父进程的信息。
|表示管线,正式上面命令的输出结果作为前面命令的输入数据。
在结果图中可以看下来进程号为4265的进程是进程号为4266进程的父进程。
grepfork表示只显示输入数据中富含./fork字符串的项目,有过滤的功能,显示的就只有兄妹进程的信息。
2、
代码中子进程在执行exec函数之前sleep(5),这样子可以有足够时间通过另外一个终端查看进程信息。exec函数中执行的是ls命令,之后一个终端执行./test命令,另一个终端输入ps-ef命令查看进程信息。在程序列举当前文件夹文件后继续输入ps-ef命令。
3、两个线程抢劫cpu资源,造成出现不同的结果
4、多线程之间存在竞争关系,数值被多个线程更改,致使结果并没有按次序显示,出现不同的结果
5、
创建进程的空间和时间开支要小于线程,进程之间有着不同的地址空间,而同一进程里的多线程则使用同一地址空间,共享该进程里的堆、数据段;
多线程的优点:
1、创建进程的空间和时间开支要小于线程,进程之间有着不同的地址空间,而同一进程里的多线程则使用同一地址空间,共享该进程里的堆、数据段;
2、方便高效的通讯方法:线程间共享显存,通讯便捷;
3、较轻的切换开支:不用切换地址空间。
当不同任务间须要大量共享数据或频繁通讯时,推荐使用多线程。
还有就是多线程编程复杂,调试复杂,多进程编程相对简单,调试也简单。
进程间不会相互影响linux下内核与应用程序之间的通信,一个线程死掉将造成整个进程死掉。
6、
先延后5秒后,输出child1processissendingmessage,再延后5秒后,输出child2processissendingmessage。父进程先接收到子进程1的消息,后接收到子进程2的消息。
7、
写好程序和Makefile文件后,步入超级用户模式,用make运行Makefile,进行模块编译。
编译好模块后就可以用insmod命令将新模块插入内核中,用lsmod命令检测模块是否早已在内核中。
使用rmmod命令可以从内核中移除模块
六、实验总结
通过此次的实验,对linux操作系统的进程有了更深入的了解linux下内核与应用程序之间的通信,学会了多线程编程,了解到了多线程和多进程之间的区别,初步认识了内核模块的编撰。
思索题
1、程序中的sleep(5)起哪些作用?
假如运行结果没有发生变化,可在进程中使用sleep(5)来挂起进程来查看结果的变化。
2、子进程1和2为何也能对管线进行操作?
实验中所用到的无名管线实际上是一个没有路径的临时文件,进程通过该文件的文件描述符来辨识它,而子进程会承继父进程的环境和上下文中的大部份内容,包括文件描述符,继而子进程也能对父进程中创建的管线进行操作。
3、一个内核模块必须具备什么内容?
任何模块都要包含的三个头文件:
#include
#include
#incldue
一个内核模块应当起码有两个函数,第一个为module_init(),是模块加载函数,当模块被插入到内核时调用它;第二个为module_exit(),是模块卸载函数,当模块从内核移走时调用它。据悉,内核模块还应有Makefile文件,其作用是形成模块的目标文件linux操作系统版本,链接到内核,编译模块。
代码链接