Linux编程基础

来源:互联网 发布:淘宝模特照片处理 编辑:程序博客网 时间:2024/05/24 06:43
实验二 Linux编程基础一、实验目的熟悉Linux下使用C语言编程的方法,通过在编程中使用进程控制系统调用功能,直观理解Linux下进程并发执行情况。二、实验题目使用vi编辑C语言源程序;分析例子程序并通过man命令熟悉相关系统调用,编写进程并发执行的程序;使用gcc、make等工具进行编译;执行编译生成的执行文件并分析结果。三、背景材料因实验用的Linux环境以字符界面为主,而Linux的字符界面并没有广泛使用的集成开发环境,经典的C语言开发模式还是使用文本编辑软件编写源程序,然后使用gcc和make工具进行编译链接,生成可执行文件。在编辑源程序环节,可以使用不同的文本编辑工具,例如在图形用户界面下可以使用gedit或者kedit;字符界面下可以使用vi、emacs、nano等编辑器;甚至可以在其它环境下编辑,然后通过ftp上传。(一)编辑器vi的使用vi或vim是Linux系统上经典的文本编辑工具,在字符界面下,广泛用于系统管理、程序开发。本实验要求熟悉vi基本操作,可以使用vi进行文本编辑。 1、调用vi最常用的命令模式是:vi filename 2、vi的三种模式Command(命令)模式,用于输入命令;Insert(插入)模式,用于插入文本;Visual(可视)模式,用于可视化的的高亮并选定正文。 3、文件的保存和退出Command模式是vi的默认模式,如果处于其它模式时,要通过ESC键切换过来,接着再输入:号时,vi会在屏幕的最下方等待输入命令;:w 保存;:w filename 另存为filename;:wq! 保存退出;:wq! filename 注:以filename为文件名保存后退出;:q! 不保存退出;:x 应该是保存并退出 ,功能和:wq!相同 4、光标移动;按ESC进入Command模式后,可以用下面的一些键位来移动光标;j 向下移动一行;k 向上移动一行;h 向左移动一个字符;l 向右移动一个字符;ctrl+b 向上移动一屏;ctrl+f 向下移动一屏;向上箭头 向上移动;向下箭头 向下移动;向左箭头 向左移动;向右箭头 向右移动;对于 j、k、l和h键,还能在这些命令的前面加上数字,比如 3j,表示向下移动3行。 5、进入插入模式i 在光标之前插入;a 在光标之后插入;I 在光标所在行的行首插入;A 在光标所在行的行末插入;o 在光标所在的行的上面插入一行;O 在光标所在的行的下面插入一行;s 删除光标后的一个字符,然后进入插入模式;S 删除光标所在的行,然后进入插入模式; 6、文本内容的删除x 删除一个字符;#x 删除几个字符,#表示数字,比如3x;dw 删除一个单词;#dw 删除几个单词,#用数字表示,比如3dw表示删除三个单词;dd 删除一行;#dd 删除多个行,#代表数字,比如3dd 表示删除光标行及光标的下两行;d$ 删除光标到行尾的内容;J 清除光标所处的行与上一行之间的空格,把光标行和上一行接在一起; 7、可视模式在最新的Linux发行版本中,vi提供了可视模式。按ESC键,然后按v就进入可视模式; 退出可视模式,还是用ESC键。可视模式提供了友好的选取文本范围,以高亮显示。 8、复制和粘帖的操作复制:对于可视模式下选中的文本,可以按y进行复制;按yy可以复制当前光标所在行。此外,删除也带有剪切的意思,当我们删除文字时,相应内容会自动复制;粘贴:可以把光标移动到某处,然后按p或shift+p键进行粘贴,其中,p 在光标之后粘帖;shift+p 在光标之前粘帖。 9、行号可以在命令模式输入 :set number 来打开行号显示,输入 :set number 来关闭行号显示。10、查找功能在命令模式下,输入/或?就可以进行查找;/SEARCH 注:正向查找,按n键把光标移动到下一个符合条件的地方;?SEARCH 注:反向查找,按shift+n 键,把光标移动到下一个符合条件的11、替换功能按ESC键进入命令模式;:s /SEARCH/REPLACE/g 注:把当前光标所处的行中的SEARCH单词,替换成REPLACE,并把所有SEARCH高亮显示;:%s /SEARCH/REPLACE 注:把文档中所有SEARCH替换成REPLACE;:#,# s /SEARCH/REPLACE/g 注:#号表示数字,表示从多少行到多少行,把SEARCH替换成REPLACE;注:命令中g表示全局查找,在指定的替换范围之外,也会把SEARCH高亮显示。(二)gcc和make的使用Linux下编辑好的C语言程序,需要使用gcc编译工具(Linux系统上一般也可以通过cc别名调用)进行编译连接,生成可执行文件。对于复杂的应用,可能把多个源程序分别编译,最后连接形成执行文件;为了有效管理这类项目,make代码维护工具可以用来定义一系列规则来管理编译连接过程。【注】Linux下的可执行文件没有特别的后缀名约定,而是通过设置“可执行”属性来区分;另外,Linux默认的执行文件搜索路径也不包括当前目录,所以编译生成的执行文件需要显示指明文件路径来执行。 1、gcc的使用 (1) 简单使用方法假设一个C语言源程序名为demo.c,根据该文件生成执行文件的最简单命令为:gcc hello.c该命令将生成默认名字为a.out的执行文件;如果希望生成执行文件的名字不同,可以在命令中通过参数指定:gcc -o hello hello.c该命令将生成名字为demo的执行文件。 (2) 分解使用实际上,gcc所做的工作包括预编译、编译、连接等多个环节,上述简单用法隐含了对这几个环节的调用,如果需要分开调用,可以通过不同的命令行参数指定:gcc -E hello.c -o hello.i-E参数指定进行预编译,预处理的宏定义插入到hello.i中;gcc -c hello.i -o hello.o-c参数指定编译为目标代码 hello.o,也可以通过源文件直接生成(gcc -c hello.c);gcc hello.o -o hello将生成可执行文件,如果由多个源程序文件生成,一般需要在生成时指定多个目标代码模块,例如:gcc hello.o e1.o s2.o -o hello(3) 常用参数gcc命令行的常用参数如下:-c 通知GCC取消链接步骤,即编译源码并在最后生成目标文件;-Dmacro 定义指定的宏,使它能够通过源码中的#ifdef进行检验;-E 不经过编译预处理程序的输出而输送至标准输出;-g3 获得有关调试程序的详细信息,它不能与-o选项联合使用;-Idirectory 在包含文件搜索路径的起点处添加指定目录;-llibrary 提示链接程序在创建最终可执行文件时包含指定的库;-O、-O2、-O3 将优化状态打开,该选项不能与-g选项联合使用;-S 要求编译程序生成来自源代码的汇编程序输出;-v 启动所有警报;-Wall 在发生警报时取消编译操作,即将警报看作是错误;-Werror 在发生警报时取消编译操作,即把报警当作是错误;-w 禁止所有的报警。 2、make的使用 (1) make工具简介make是一种代码维护工具,在大中型项目中,根据程序各个模块的更新情况,自动的维护和生成目标。能很好的做到“不多、不重、不漏”:•不多:只更新那些需要更新的文件,而不动那些并不过时的东西;•不重:是指当make对某个文件进行更新时,即使有很多文件过时,也将只更新一次;•不漏:是指他不会漏下任何应该更新的文件。make在使用时有一系列的规则,将根据这些规则来解释其配置脚本,以达到设计目的。配置脚本的缺省名是makefile或Makefile,也可在命令行指定其它文件名。使用形式为:make [option] [macrodef] [target]option指出make的工作行为,具体参数可参考man手册页。 (2) makefile文件编写make工具使用的关键是编写高效、简洁、正确的makefile,这需要学习和实践。虽然make工具的使用有较高的门槛,但是一旦掌握,其带来的灵活和便捷远远超过一般IDE所能提供的管理功能。实际makefile文件编写涉及的知识很多,有专著专门最次讲解。此处只是介绍概貌,借助一个简单的例子来说明:假设一个项目hello,依赖于hello.o、e1.o、e2.o,而hello.o依赖于hello.c、hello.h,e1.o依赖于e1.c、hello.h,e2.o依赖于e2.c;这样形成一棵依赖关系树,父节点依赖于子节点。使用make进行维护时,会对这棵树进行一次遍历,如果发现子节点形成的时间晚于父节点形成的时间便开始调用makefile中指定的命令进行维护。针对此例子的makefile示例如下:hello: hello.o e1.o e2.o gcc -o hello hello.o e1.o e2.o main.o: hello.c hello.h gcc -c hello.c e1.o: e1.c hello.h gcc -c e1.c hello.h e2.o: e2.c gcc -c e2.cmakefile放置在与项目源程序文件相同目录中,在该目录中执行make hello或者make命令(命令行未target时会默认使用makefile的第一个target),将会根据makefile中定义的依赖关系依次执行编译、连接各个命令,生成hello执行文件。实际项目的makefile因为会使用大量的宏、条件变量以及缺省规则,对初学者而言较难理解。对于一般的开源项目,在编写makefile时,target的命名都会遵循一些预定俗称的规则,常见的用法包括:make all编译项目中所有实际目标make install进行安装make clean清除所有中间文件 (3) 缺省规则和简单用法make的缺省规则是系统或者自定义的一些规则,在定义时不指出全名,而是根据文件扩展名定义一类依赖关系和相关命令。例如,与c语言相关的缺省规则包括: .c: $(CC) $(FLAGS) -o $@ $< .c .o: $(CC) $(FLAGS) -c $@ $<两条规则的含义为:对于.c扩展名的文件,调用编译器(通过环境变量CC定义,默认为gcc)生成与.c文件对应名字的执行文件;对于.o、.c扩展名配对的情况,调用编译器进行编译,生成与.c文件对应名字的.o目标文件。根据这些缺省规则,可以在简单情况下不编写makefile使用make工具。例如,对于根据hello.c生成hello执行文件的情况,可以直接使用命令make hello效果等同于:gcc -o hello hello.c(三)需要用到的系统调用实验要求在例子程序基础上编程验证Linux下进程并发情况,需要用到的系统调用和库函数在下面列出,详细的使用方法说明通过“man 2 系统调用名”或者“man 3 函数名”命令获取。fork()创建一个子进程,通过返回值区分是在父进程还是子进程中执行;wait()等待子进程执行完成;sleep()导致调用进程睡眠指定秒数;getpid()获取当前进程id;getppid()获取父进程id。四、实验内容为便于掌握Linux环境下进行C语言编程的基本技能,本实验提供源程序例子,实验内容要在给出的例子程序基础上,根据要求进行修改,对执行结果进行分析。 1、子进程对存储空间的复制 (1) 使用文本编辑器输入源程序输入如下源程序:#include #include #include int main(void){ int x, i; printf("Input a initial value for i: "); scanf("%d", &i); while((x=fork())==-1); if(x==0)/* child run */ { printf("When child runs, i=%d/n", i); printf("Input a value in child: "); scanf("%d", &i); printf("i=%d/n", i); } else/* parent run */ { wait(); printf("After child runs, in parent, i=%d/n", i); }}(2) 预测程序的执行结果阅读程序,根据自己的理解,预期程序执行后的结果。 (3) 实际执行结果分析编译生成执行文件,执行后记录结果,说明与预期的结果是否一致。分析为什么是这样的结果。 2、父子进程执行过程分析 (1) 按照给定框架编程按照如下程序框架,完成源程序编写:// ①pid=fork(); // ② if(pid==0) { sleep(3); printf("Child: pid=%d, ppid=%d/n", getpid(), getppid()); }else { printf("Parent: Child=%d, pid=%d, ppid=%d/n", pid, getpid(), getppid()); wait(); printf("After Child ends./n"); }printf("In which process?/n"); // ③ (2) 预测程序的执行结果阅读程序,根据自己的理解,预期程序执行后的结果。 (3) 实际执行结果分析编译生成执行文件,执行后记录结果,说明与预期的结果是否一致。分析为什么是这样的结果。 (4) 修改程序并分析执行结果把程序框架中最后一句输出语句(位置③处)分别移至位置①和②处,预期输出结果是什么?实际执行结果如何?分析原因。 (5) 修改程序验证父子进程关系修改程序,使父进程先执行完成,验证子进程是否会一起终止?如果不是,前后子进程的父进程号是否变化?记录并分析结果。五、实验报告书写要求应在实验报告中说明如下事项: 1、所使用的文本编辑器; 2、编译生成执行文件的命令; 3、相关程序的名称及存储位置,以便指导教师抽查; 4、实验内容1的结果:包括预期结果和实际执行结果,以及结果分析; 5、实验内容2的结果:包括预期结果和实际执行结果,对结果的分析;按照要求进行修改后的预期结果、实际结果及分析。
原创粉丝点击