本文已参与「新人创作礼」活动,一起开启掘金创作之路
一、实验设备 :
1.VMware Workstation Pro;
2.Redhat。
二、实验目的 :
1.熟悉并掌握linux下C语言程序基本方法;
2.熟悉并掌握gcc及常用参数编译C/C++源程序;
3.熟悉并掌握利用GDB调试工具调试C/C++程序;
4.熟悉并掌握利用MAKE工具维护及自动编译应用程序;
5.掌握进程相关系统调用。
三、实验要求:
1.熟练使用GCC编译工具;
2.熟练使用GDB调试工具;
3.熟练使用MAKE工具;
4.了解linux进程相关概念和明确进程的含义;
5.认识并了解并发执行的实质并掌握fork()系统调用的相关编程。
四、实验内容:
1.linux上的C/C++编译器,位置/usr/bin或usr/local/bin可编译C/C++源程序。通常在编译两个或少数几个C/C++源文件时,利用GCC编译、连接并生成可执行文件。请验证下面简单C程序的编译:
设两个源文件main.cpp和factorial.cpp俩源文件,现在要编译生成一个计算阶乘的程序。
图1-1 main.cpp
图1-2 factorial.cpp
图1-3 factorial可执行文件的执行
2.利用GDB调试有错误程序:利用gdb调试有错误的C/C++程序使用gdb调试程序之前,必须使用-g选项编译源文件。
1)运行gdb bugging命令,装入bugging可执行文件;
图2-1 gdb bugging装入可执行文件
2)执行装入的bugging命令:(run);
图2-2 gdb run命令
3)使用where命令查看程序出错的地方:(显示第6行错误)利用list命令查看调用gets函数附近的代码:(list);
图2-3 gdb where指令
4)唯一能够导致gets函数出错的因素就是变量string。用print命令查看string的值:(p string);
图2-4 gdb p string指令
5)在gdb中,可以直接修改变量值,只要将string取一个合法的指针值就可以了,为此在第6行设置断点:(br 6);
图2-5 gdb br 6设置断点
6)程序重新运行到第6行处停止,这时可以用set variable命令修改string的取值:(set string=”init”);
图2-6 gdb set string=”init”指令
7)如何继续运行,将看到正确的程序运行结果。(c)。
图2-7 gdb cont继续运行指令
3.利用make工具实现自动编译和工程管理。验证下面题目。
设计一个程序,程序运行时从三道题目中随机选取一道,题存放在二维数组中。
(1)分析程序,组织文件
fun_main.c 从三道题目中随机选取一道题。
图3-1 fun_main.c
head_random.h 包含把函数声明和用的库函数。
图3-2 head_random.h
fun_random.c文件中定义随见函数,返回随机数,并返回主函数。
图3-3 fun_random.c
图3-4 makefile文件
图3-5 运行fun_make文件
4.编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示’a’,子进程分别显示字符’b’和字符’c’。试观察记录屏幕上的显示结果,并分析原因。
源程序:如图4-1。
输出结果:bb(如图4-2)。
原因:这里是因为打漏了一个括号,在第4行,==的优先级比=高,所以每一次都会比较是否=-1,不等返回0,所以无论父子进程,都会赋值为0,输出结果为bb。
图4-1 process.c 源程序
图4-2 process运行结果
5.修改上述程序,每一个进程循环显示一句话。子进程显示’daughter...’及’son......’,父进程显示’parent......’,观察结果,分析原因。
源程序:如图5-1。
输出结果:如图5-2。
分析原因:同第四题分析原因,如果修改第四行和第九行分别为,(p1=fork())==-1和(p2=fork())==-1)则会出现先分别输出daughter,parent,son,因为进程的异步性,导致输出不一。
图5-1 pro.c源代码
图5-2 pro运行结果
五. 实验心得
通过在linux上进行C/C++编程,了解到了可执行文件的生成过程,从.c源文件,预处理成.i文件,编译成.s汇编文件,汇编成.o可执行文件,最后链接单个或多个.o文件成可执行文件,了解到gdb调试工具,make管理程序工具。最后再进程实验卡点,因为少了个括号,导致优先级不符合预先结果,最后检查得到解决。