实验2 Linux下基本编程

实验2 Linux下基本编程

一、实验目的

1.掌握vim编译器

2.掌握gcc编译器的使用

3.了解fork()程序

二、实验工具与设备

1.实验设备:计算机(带CD-ROM)一台。

三、实验预备知识

1. vim的编辑器

使用语法:Vim <被编辑的文件名>

Vim有三种模式:命令模式、插入模式、最后行模式。

命令模式:

刚启动Vim后,就处于该模式。在此模式下,允许用Vim的子命

令来编辑文件或转移到其它模式。如:

x命令:删除光标上面的字符。

方向键:移动光标。

i命令:进入插入模式,可在当前光标处插入字符。

a命令:进入插入模式,可在当前光标后插入字符。

R命令:从当前光标处开始替换文本。

r命令:替换当前光标处字符。

~命令:对当前光标处字母进行大小写转换。

dd命令:删除光标所在行。

dw命令:删除光标所在处字。

h命令:光标左移。

l命令:光标右移。

k命令:光标上移。

j命令:光标下移。

:命令:进入最后一行模式。

插入模式:

此模式下允许输入文本,用回车键换行,Esc 进入命令模式。

最后一行模式:

w命令:将文件存盘,但不退出。

wq命令:将文件存盘,并退出。

q! 命令:不保存文件并退出。

r命令:将另一个文件内容插入当前光标处。

2.gcc编译器

Unix 上使用的C 语言编译器cc,在Linux上的派生就是gcc。在使用vim编写完源程

序之后,返回到shell下面,使用gcc对源程序进行编译的命令是:

gcc 源程序

其中,“源程序”即为你编写的以.c 为扩展名的C 语言源代码文件。

如果源代码没有语法错误,使用以上命令编译,会在当前目录下生成一个名为a.out

的可执行文件。如果源代码有语法错误,则不会生成任何文件,gcc编译器会在shell中

提示你错误的地点和类型。

也可以使用以下方法编译源代码文件,生成自命名的可执行文件:

gcc 源文件–o 自命名的文件名

执行当前目录下的编译生成的可执行文件,使用以下格式:

./可执行文件名

 

 

 

 

3.fork() 函数说明

pid_t fork(void)

fork()会产生一个新的子进程。该函数包含于头文件unistd.h 中。其子进程会复制

父进程的数据与堆栈空间,并继承父进程的用户代码、组代码、环境变量、已打开的文

件代码、工作目录和资源限制等。Linux 使用copy-on-write(COW)技术,只有当其中一

进程试图修改欲复制的空间时才会做真正的复制动作,由于这些继承的信息是复制而

来,并非指相同的内存空间,因此子进程对这些变量的修改和父进程并不会同步。此

外,子进程不会继承父进程的文件锁定和未处理的信号。注意,Linux不保证子进程会比

父进程先执行或晚执行,因此编写程序时要留意死锁或竞争条件的发生。

返回值,如果fork()调用成功则在父进程会返回新建立的子进程代码(PID),而在新

建立的子进程中则返回0。如果fork() 失败则直接返回-1,失败原因存于errno中。失

败的原因有三个:

1) 系统内存不够;

2) 进程表满(容量一般为200~400);

3) 用户的子进程太多(一般不超过25个)。

错误代码:EAGAIN 内存不足;ENOMEM 内存不足,无法配置核心所需的数据结构空

间。

 

四、实验内容和步骤

实验一:

在Linux环境下,用c语言编程,使用系统调用fork创建进程多个子进程。

(1)在终端里输入vim a.c,启动vi.

(2)按a或者i进入插入模式,在里面输入以下代码。

#include "stdio.h"

#include "sys/types.h"

#include "unistd.h"

int main()

{

 pid_t pid1;

pid_t pid2;

pid1 = fork();

pid2 = fork();

printf("pid1:%d, pid2:%d\n", pid1, pid2);

}

(3)按Esc键进入命令模式,输入:和wq 进行保存退出vim.

(4)用gcc编译器编译该程序: gcc –o a a.c –ggdb

(5)运行刚刚编译的程序:./a

要求:

A. 请说出执行这个程序后,将一共运行几个进程。

B. 观察运行结果,并给出分析与解释。

 

这个程序运行后,一共将运行4个进程。这4个进程并没有严格的区分先后顺序。

刚开始未执行fork()函数时,父进程的pid1和pid2均为0,执行第一个fork()函数时,复制父进程得到一个子进程f1,f1的pid1和pid2均为0,父进程的pid1=f1的id;

执行第二个fork()函数时,继续复制父进程得到子进程f2,则父进程的pid1=f1的id,pid2=f2的id,f2的pid1=f1的id,f2的pid2=0;

复制进程f1得到进程f11,则f1的pid1=0,f1的pid2=f11的id,f11的pid1和pid2均为0;

 

实验二:

首先分析一下代码运行时其输出结果有哪几种可能性,按照实验1步骤编译调试观察其实际输出情况,比较两者的差异,分析其中的原因。

void main (void)

{    int   x=5;

if( fork( ) )

  {

x+=30;

        printf (“%d\n”,x);

}

 else

      printf(“%d\n”,x);

 printf((“%d\n”,x);

}

(写出可能的实验结果及其分析说明)

可能的输出结果:

1.35 5 35 5父进程执行if语句里的printf然后子进程执行else语句里的printf,父进程执行最后一个printf,子进程执行最后一个printf

2.5 35 35 5子进程执行else语句里的printf,父进程执行if语句里的printf,父进程执行最后一个printf,子进程执行最后一个printf

3.35 5 5 35父进程执行if语句里的printf然后子进程执行else语句里的printf,子进程执行最后一个printf,父进程执行最后一个printf

4.5 35 5 35子进程执行if语句里的printf然后父进程执行else语句里的printf,父进程执行最后一个printf,子进程执行最后一个printf

5.35 35 5 5父进程执行if语句里的printf然后父进程执行最后一个printf,子进程执行else语句里的printf,子进程执行最后一个printf

6.5 5 35 35子进程执行if语句里的printf然后子进程执行最后一个printf,父进程执行else语句里的printf,父进程执行最后一个printf

 

 

五、实验总结

1.写出实验报告。

2. 利用vimlinux文本文件进行编辑。

3.编写fork()程序,并利用gcc进行编译、调试和运行。

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(操作系统学习)