linux操作系统分析实验一

该实验所有代码都是在ubuntu20.4系统下运行的
一、实验目的

1 理解Linux下进程的结构;
2 理解Linux下产生新进程的方法(系统调用—fork函数);
3 掌握如何启动另一程序的执行;
4 理解Linux下线程的结构;
5 理解Linux下产生新线程的方法;
6 理解Linux系统下多进程与多线程的区别
7 了解什么是管道
8 熟悉UNIX/LINUX支持的管道通信方式
9 理解内核模块的编写和装载方法
10 Gdb 调试工具的熟练使用

二 实验环境
Ubuntu linux
三 实验内容
1 利用fork函数创建新进程,并根据fork函数的返回值,判断自己是处于父进程还是子进程中;
2 在新创建的子进程中,使用exec类的函数启动另一程序的执行;分析多进程时系统的运行状态和输出结果;
3 利用最常用的三个函数pthread_create,pthread_join和pthread_exit编写了一个最简单的多线程程序。理解多线程的运行和输出情况;
4 利用信号量机制控制多线程的运行顺序,并实现多线程中数据的共享;
5 分析Linux系统下多进程与多线程中的区别。
6 编写程序实现进程的管道通信。用系统调用pipe( )建立一管道,二个子进程P1和P2分别向管道各写一句话:
Child 1 is sending a message!
Child 2 is sending a message!
父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。
7 编写一个HelloWorld内核模块,并进行装载和卸载操作

实验中用到的系统调用函数:
fork()、exec()、pthread_create()、pthread_join()、read()、write()、lockf()

实验步骤
1 利用fork函数编写一个简单的多进程程序,用ps命令查看系统中进程的运行状况,并分析输出结果。
2 在上面的多进程程序中利用exec函数,启动另一个程序的执行。用ps命令显示本机运行的所有进程的详细列表,并分析列表中不同进程的内存占用情况。
3 编写一个最简单的多线程程序。理解多线程的运行和输出情况;
4 利用信号量机制控制多线程的运行顺序,分析多线程中数据的共享情况;
5 分析Linux系统下多进程与多线程中的区别。
6 编写程序实现进程的管道通信。用系统调用pipe( )建立一管道,二个子进程P1和P2分别向管道各写一句话:
Child 1 is sending a message!
Child 2 is sending a message!
父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。
7 编写一个HelloWorld内核模块,并进行装载和卸载操作
8 调试分析结果,给出总结体会。

五、实验结果及分析
1、
在代码中添加sleep()目的是让进程不那么快结束掉,不然一下子就执行完了,如果此时再输入ps命令的话就看不到父子进程信息了。
首先使用gcc 命令编译代码,然后一个终端执行./fork命令,另一个终端输入ps -ef | grep fork命令查看进程信息。
其中命令ps -ef,参数-e表示显示系统内所有进程信息,参数-f表示使用完整的格式显示进程信息,如果不使用-f参数的话,就不能看到父进程的信息。
|表示管道,即将前面命令的输出结果作为后面命令的输入数据。
在结果图中可以看出来进程号为4265的进程是进程号为4266进程的父进程。
grep fork表示只显示输入数据中含有./fork字符串的项目,有过滤的功能,显示的就只有父子进程的信息。

在这里插入图片描述

2、
代码中子进程在执行exec函数之前sleep(5),这样子可以有足够时间通过另外一个终端查看进程信息。exec函数中执行的是ls命令,然后一个终端执行./test命令,另一个终端输入ps -ef命令查看进程信息。在程序列出当前文件夹文件后继续输入ps -ef命令。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、两个线程抢夺cpu资源,导致出现不同的结果
在这里插入图片描述

在这里插入图片描述

4、多线程之间存在竞争关系,数值被多个线程修改,导致结果并没有按顺序显示,出现不同的结果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5、
创建进程的空间和时间开销要大于线程,进程之间有着不同的地址空间,而同一进程里的多线程则使用同一地址空间,共享该进程里的堆、数据段;
多线程的优点:
1、创建进程的空间和时间开销要大于线程,进程之间有着不同的地址空间,而同一进程里的多线程则使用同一地址空间,共享该进程里的堆、数据段;
2、方便高效的通信方式:线程间共享内存,通信方便;
3、较轻的切换开销 :不用切换地址空间。
当不同任务间需要大量共享数据或频繁通信时,推荐使用多线程。

还有就是多线程编程复杂,调试复杂,多进程编程相对简单,调试也简单。
进程间不会互相影响,一个线程挂掉将导致整个进程挂掉。

6、
先延迟5秒后,输出child 1 process is sending message,再延迟5秒后,输出 child 2 process is sending message。父进程先接收到子进程1的消息,后接收到子进程2的消息。
在这里插入图片描述

7、
写好程序和Makefile文件后,进入超级用户模式,用make运行Makefile,进行模块编译。
编译好模块后就可以用insmod命令将新模块插入内核中,用lsmod命令检查模块是否已经在内核中。
使用rmmod命令可以从内核中移除模块

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

六、实验总结
通过这次的实验,对linux操作系统的进程有了更深入的了解,学会了多线程编程,了解到了多线程和多进程之间的区别,初步认识了内核模块的编写。

思考题

1、程序中的sleep(5)起什么作用?
如果运行结果没有发生变化,可在进程中使用sleep(5)来挂起进程来查看结果的变化。
2、子进程1和2为什么也能对管道进行操作?
实验中所用到的无名管道实际上是一个没有路径的临时文件,进程通过该文件的文件描述符来识别它,而子进程会继承父进程的环境和上下文中的大部分内容,包括文件描述符,从而子进程也能对父进程中创建的管道进行操作。

3、一个内核模块必须具备哪些内容?
任何模块都要包含的三个头文件:
#include <linux/module.h>
#include <linux/kernel.h>
#incldue <linux/init.h>
一个内核模块应该至少有两个函数,第一个为module_init(),是模块加载函数,当模块被插入到内核时调用它;第二个为module_exit(),是模块卸载函数,当模块从内核移走时调用它。此外,内核模块还应有Makefile文件,其作用是产生模块的目标文件,链接到内核,编译模块。

代码链接
https://pan.baidu.com/s/1MdfMn2nM7-eHJmiLPZmqLQ

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值