Linux全部教学讲解课件_第1页
Linux全部教学讲解课件_第2页
Linux全部教学讲解课件_第3页
Linux全部教学讲解课件_第4页
Linux全部教学讲解课件_第5页
已阅读5页,还剩508页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Linux编程及应用

邮箱:1参考教材:

linux软件工程师(C语言)实用教程刘加海,张益先主编科学出版社《UNIX环境高级编程》(第2版),史蒂文斯著Linux高级程序设计:(英)美斯特,(美)布卢著,陈健等译人民邮电出版社2课程要求:作业和平时表现:20%

上机实验:20%

期末考试:60%3课程内容:Shell编程Linux系统程序设计基础文件分割和多文件编译linux环境下系统函数的使用文件的操作串行通信进程控制进程间的通信网络程序设计4第一章Shell编程5本章学习目标了解shell编程的基本概念及其特点掌握shell各种变量的区别掌握正则表达式的使用方法熟悉shell的各种流程控制了解shell的函数6*目录1.1Shell概述1.2创建和执行shell程序1.3变量1.4位置参数1.5特殊字符1.6运算符1.7输入和输出1.8表达式的比较1.9流程控制语句1.10函数7*1.1Shell概述Shell就像一个壳层,这个壳层介于用户和操作系统之间,负责将用户的命令解释为操作系统可以接收的低级语言,并将操作系统响应的信息以用户可以了解的方式来显示。硬件操作系统KernelShell8*1.1Shell概述Shell角色图Shell操作系统kernel硬件9*1.1Shell概述从用户登陆到注销期间,用户输入的每个命令都会经过解译及执行,其负责机制就是shell。shell是一个命令语言解释器,它拥有自己内建的shell命令集,shell也能被系统中其他应用程序所调用。用户在提示符下输入的命令都由shell先解释然后传给Linux核心。有一些命令,如改变工作目录命令cd,是shell内置命令。还有一些命令,例如拷贝命令cp和移动命令mv,是存在于文件系统中某个目录下的单独的程序。对用户而言,不必关心一个命令是建立在shell内部还是一个单独的程序。

10*1.1Shell概述shell的主要版本在Linux系统中常见的shell版本有以下几种。(1)Bourneshell(sh):它是UNIX最初使用的shell,并且在每种UNIX都可以使用。它在shell编程方面相当优秀,但处理与用户的交互方面不如其他几种shell。(2)Cshell(csh):它最初由BillJoy编写,它更多地考虑了用户界面的友好性,支持如命令补齐等一些Bourneshell所不支持的特性,但其编程接口做得不如Bourneshell。Cshell被很多C程序员使用,因为Cshell的语法和C语言的很相似,Cshell也由此得名。(3)Kornshell(ksh):它集合了Cshell和Bourneshell的优点,并且和Bourneshell完全兼容。11*1.1Shell概述(4)BourneAgainshell(bash):bash是大多数Linux系统的默认shell。它是Bourneshell的扩展,并与Bourneshell完全向后兼容,而且在Bourneshell的基础上增加和增强了很多特性。。(5)tcsh:它是Cshell的一个扩展版本,与csh完全向后兼容,但它包含了更多使用户感觉方便的新特性,其最大的提高是在命令行编辑和历史浏览方面。它不仅和Bashshell提示符兼容,而且还提供比Bashshell更多的提示符参数。(6)pdksh:它是一个专门为Linux系统编写的Kornshell(ksh)的扩展版本。Ksh是一个商用shell,不能免费提供,而pdksh是免费的。12*表1Linux中的各种shellshell名称描述位置

ash一个小shell(和sh类似)/bin/ashash.static一个不依靠软件库的ash版本/bin/ash.staticbashBourneAgainShell/bin/bashbash2BourneAgainShell的新版本/bin/bash2bshash的一个符号链接/bin/bshcshCshell,tcsh的一个符号链接/bin/cshksh公共域受限制的shell(针对网络操作)/usr/bin/kshshbash的一个符号链接/bin/shtcsh和csh兼容的shell/bin/tcshzsh一个和csh,ksh和sh兼容的shell/bin/zsh1.1Shell概述13*1.1Shell概述判断登入shell使用echo命令来查询系统的“SHELL”环境变量,命令如下:#echo$SHELL14*1.1Shell概述暂时变更shell除非是在受限的shell中,否则若要变更使用shell,只要执行该Shell程序名称(shell_name),即可切换到不同的Shell。如:#sh(或#csh等等)此处的shell_name是指shell的名称(例如,sh或csh)。暂时变更shell,可在其它的shell中进行试验。键入exit或CTRL-D可以回到原始的shell中。15*1.1Shell概述16*1.1Shell概述Shell功能介绍交互式处理(InteractiveProcessing)接收来自用户输入的命令后,shell会根据命令类型的不同来执行,执行完毕后,shell会将结果回传给用户,并等待用户下一次输入。用户执行exit或是按Ctrl+D来注销shell才会结束。17*1.1Shell概述命令补全功能指用户输入命令后,有时不需输入完整的命令,而系统会自动找出最符合的命令名称,这种功能可以节省输入长串命令的时间。不需要输入完整的文件名,只需输入开头几个字母,然后按Tab键时候,系统会补充完整,连续按两次Tab(Esc)键系统会显示所有符合输入前缀的文件名称。若忘了命令的全名,而只记得命令的开头字母,按Tab键一次会补充完整,连续按两次Tab(Esc)键系统会显示所有符合输入前缀的命令名称。18*1.1Shell概述查阅历史记录-history命令在Linux系统上输入命令并按下Enter后,这个命令就会存放在命令记录表(~/.bash_history)中,预定的记录为1000笔,这些都定义在环境变量中。列出所有的历史记录:#history只列出最近5笔记录犯例:#history5使用命令记录号码执行命令:#!561重复执行上一个命令:#!!执行最后一次以ls开头的命令:#!ls19*1.1Shell概述别名(Alias)功能查询目前系统所有别名:#alias设置别名:#aliasdir=‘ls-l’使用别名:#dir/etc取消别名:#unaliasdiralias命令的效力仅限于该次登录,在注销系统后,这个别名的定义就会消失。如果希望每次登陆都使用这些别名,则应该将别名的设置加入“~/.bashrc”文件中,若是写入“/etc/bashrc”文件中,则系统上的所有用户都能使用这个别名。20*1.2创建和执行shell程序不同的shell其编程(命令)语法有所不同较常见的shell脚本是bash另一种较常见的shell脚本是tcsh,其命令/语法类似C语言学习脚本编程的原因在有些场合,希望一些常用的命令集能用一个命令实现;可以处理一些特定的问题,如计算每月上网的总时数。21*1.2创建和执行shell程序Shell脚本编程前的准备文本编辑器(vi或vim,gedit等)脚本解释程序(bash,tcsh等)其他工具(用来扩充Shell脚本的功能,如:grep,wc)22*1.2创建和执行shell程序例:显示当前的日期时间、执行路径、用户账号及所在的目录位置。1.建立shell脚本如建立一个名为ex1的shell脚本,可提示符后输入命令:$viex1.sh23*1.2创建和执行shell程序在vi编辑器中输入下列内容:

#!/bin/bash#Thisscriptisatest!echo–n“Dateandtimeis:”dateecho–n“Theexecutablepathis:”$PATHecho“Yournameis:`whoami`”echo-n“Yourcurrentdirectoryis:”pwd#end2.用三种方法执行shell脚本24*1.2创建和执行shell程序(1)输入定向到shell脚本。其一般形式是:$bash<脚本名例如:$bash<ex1(2)以脚本名作为参数。其一般形式为:$bash脚本名[参数]例如:$bashex1如果以当前shell执行一个shell脚本,则可以使用如下简便形式:$.脚本名[参数](3)使用chmod命令将shell脚本的权限设置为可执行,然后在提示符下直接执行它。例如:

$chmoda+xex1$./ex125*1.2创建和执行shell程序在编写shell时,第一行一定要指明系统需要那种shell解释你的shell程序,如:#!/bin/bash,#!/bin/csh,/bin/tcsh,还是#!/bin/pdksh。用上面执行shell脚本的三种方法分别体会这句话的作用。26*1.3变量3种类型:环境变量:系统提供,不用定义,可以修改内部变量:系统提供,不用定义,不能修改用户变量:用户定义,可以修改与其他语言的区别:非类型性质,也就是不必指定变量是数字或字符串等。27*1.3变量环境变量Linux环境(也称为shell环境)由许多变量及这些变量的值组成,由这些变量和变量的值决定环境外观。这些变量就是环境变量。主要环境变量的有:(1)HOME:用户目录的全路径名。(2)UID当前用户的识别字,取值是由数位构成的字串。(3)LOGNAME:即用户的注册名,由Linux自动设置。(4)MAIL:用户的系统信箱的路径。(5)PATH:shell从中查找命令的目录列表。28*1.3变量(6)PS1:shell的主提示符,在特权用户下,默认的主提示符是#,在普通用户下,默认的主提示符是$。(7)PS2:在Shell接收用户输入命令的过程中,如果用户在输入行的末尾输入“\”然后回车,或者当用户按回车键时Shell判断出用户输入的命令没有结束时,就显示这个辅助提示符,提示用户继续输入命令的其余部分,默认的辅助提示符是>。(8)PWD:用户当前工作目录的绝对路径名,该变量的取值随cd命令的使用而变化。它指出用户目前在Linux文件系统中处在什么位置。它是由Linux自动设置的。(9)SHELL:用户当前使用的shell。它也指出你的shell解释程序放在什么地方。(10)TERM:用户终端类型。29*1.3变量$HOME/.bash_profile(/etc/profile)env30*1.3变量export在任何时候,创建的变量都只是当前Shell的局部变量,不能被Shell运行的其他命令或Shell程序所用,export命令可以将一个局部变量提供给Shell执行的其他命令使用。31*1.3变量内部变量(预定义变量)内部变量是Linux所提供的一种特殊类型的变量,这类变量在程序中用来作出判断。在shell程序内这类变量的值是不能修改的。部分内部变量是:$#——传送给shell程序的位置参数的个数$?——命令执行后返回的状态$0——当前执行的进程的名称$*——调用shell程序时所传送的全部参数成的单字符串32*1.3变量ex1.sh的示范例子:

#ex9_3_1.shecho“Numberofparametersis”$#echo“Programnameis”$0echo“Parametersasasinglestringis”$*

在bash中,从命令行中执行ex9_3_1.sh如下:

#.ex9_3_1.shzhangli

将得到如下的结果:33*1.3变量用户变量1.变量名用户定义的变量是最普通的shell变量。变量名是以字母或下线符开头的字母、数字和下线符序列,并且大小写字母意义不同。在定义变量时,变量名前不应加符号$,在引用变量的内容时则应在变量名前加$;在给变量赋值时,等号两边一定不能留空格,若变量中本身就包含了空格,则整个字串都要用双引号括起来。在编写Shell程序时,为了使变量名和命令名相区别,建议所有的变量名都用大写字母来表示。34*1.3变量2.变量赋值给变量赋值的过程也是声明一个变量的过程。set显示本地所有的变量变量的赋值很简单,其一般形式是:变量名=字符串/数字例如:lcount=0myname=fedora有时想在说明一个变量并对它设置为一个特定值后就不在改变它的值时,可以用下面的命令来保证一个变量的只读性:readonly

变量名35*1.3变量36*1.3变量37*1.3变量3.访问变量值可以通过给变量名加上前缀$(美元符)来访问变量的值。例如:如果要把myname的值分配给变量yourname,那么可以执行下面的命令:yourname=$myname38*1.3变量4.变量清除unsetvariable-name例:39*1.3变量给变量赋值

命令环境locunt=0pdksh和bashsetlocunt=0tcshmyname=Sanjivpdksh和bashsetname=Sanjivtcshmyname=’SanjivGuha’pdksh和bashsetname=’SanjivGuha’tcsh40*1.3变量给变量赋值访问变量值

命令环境lcount=$varpdksh和bashsetlcount=$vartcsh41*1.4位置参数1.位置参数及引用可以编写一个shell脚本,当从命令行或者从其他shell脚本中调用它的时候,这个脚本接收若干参数。这些选项是通过Linux作为位置参数(positionalparameter)提供给shell程序的。在shell脚本中应有变量,接收实参,这类变量的名称很特别,分别是1,2,3,…,这类变量称为位置变量。位置参数1存放在位置变量1中,位置参数2存放位置变量2中,……,在程序中可以使用$1,$2,……来访问。42*1.4位置参数2.用set命令为位置参数赋值在shell程序中可以利用set命令为位置参数赋值或重新赋值。(1)一般格式:set[参数表](2)说明:该命令后面无参数时,将显示系统中的系统变量的值;如果有参数将分别给位置参数赋值。43*1.4位置参数3.位置参数移动当位置变量个数超出9个时,就不能直接引用位置大于9的位置变量了,必须用shift命令移动位置参数。(1)一般形式:shift[n](2)说明:每次执行时,把位置参数向左移动n位。如果没有参数,每次执行时,把位置参数向左移动1位。44*1.4位置参数下述是一个shell程序的ex9_4_1.sh,只带了一个参数(名字),并在屏幕上显示这个名字:#Namedisplayprogramif[$#-eq0]thenecho“Namenotprovided”elseecho”Yournameis$1”fi45*1.4位置参数在bash中,如果执行ex9_4_1.sh如下:#.ex9_4_1.sh将得到输出:Namenotprovided但是,如果执行ex9_4_1.sh如下:#.ex9_4_1.shzhang则得到如下的输出:Yournameiszhangex9_4_1.sh还说明了shell编程的另一个方面,即内部变量。在ex9_4_1.sh中的变量$#是内部变量,并提供传给shell程序的位置参数的数目。46*1.4位置参数位置变量小结位置变量表示$0,$1……$9在脚本中使用位置参数向系统命令传递参数$0$1$2$3$4$5$6$7$8$9脚本名字ABCDEF47*1.4位置参数48*1.5特殊字符特殊字符中的某些字符字符说明

$指出shell变量名的开始

|把标准输出通过管道传送到下个命令

#标记注释开始

&在后台执行进程

?匹配一个字符*匹配一个或几个字符

>输出重定向操作符

<输入重定向操作符49*1.5特殊字符特殊字符中的某些字符(续)

字符说明

>>输出重定向操作符{添加到文件}<<跟在输入结束字符串后(HERE)操作符

[]列出字符的范围

[a-z]意a到z的全部字符

[a,z]意指a或z字符

.filmname执行(“源”)文件空格在两个字之间的间隔符50*1.5特殊字符注释符‘#’在shell编程中经常要对某些正文行进行注释,以增加程序的可读性。在Shell中以字符“#”开头的正文行表示注释行。51*1.5特殊字符双引号在字符串含有嵌入的空格时,用双引号括起来。这是一个有关bash的例子:var=”teststring”newvar=”Valueofvaris$var”echo$newvar执行上面的三行shell程序,可得到如下的结果:Valueofvaristeststring52*1.5特殊字符单引号利用单引号把字符括起来,以阻止shell解析变量。把前面的双引号改为单引号var=”teststring”newvar=‘Valueofvaris$var’echo$newvar执行程序可得到如下的结果:Valueofvaris$var53*1.5特殊字符反斜杠在某个字符前利用反斜杠可以阻止shell把后面的字符解释为特殊字符。例如,把$test的值赋给变量var。输入如下命令:var=$test如下命令才把$test存放在var中:var=\$test54*1.5特殊字符55*1.5特殊字符反引号通知shell执行由反引号定义的字符串。当需要把执行命令的结果存放在变量中时,就可以在shell程序中利用反引号。例1:统计当前目录下一个文件中test.txt有几行并把结果存在叫做var的变量中:var=`wc-ltest.txt`例2:string=”currentdirectoryis`pwd`”echo$stringcurrentdirectouris/home/xyz56*1.5特殊字符示例代码运行结果57*1.5特殊字符管道可以通过管道把一个命令的输出传递给另一个命令作为输入。管道用竖杠|表示。格式:命令1|命令2举例:catmyls-l|grep"myfile"58*1.5特殊字符文件重定向改变程序运行的输入来源和输出地点。重定向标准输出catfile|sort>sort.outpwd>>path.out>newfile重定向标准输入sort<filesort<name.txt>name.out59*1.5特殊字符60*1.5特殊字符61*1.6运算符运算符是对计算机发的指令运算对象数字、字符变量表达式表达式:运算符和运算对象的组合体62*1.6运算符$[]表示形式告诉shell对方括号中的表达式求值$[2+8]63*1.6运算符赋值运算符=、+=、-=、*=、/=、%=、&=、^=、|=、<<=、>>=64*1.6运算符表达式替换$[]和$(())两种格式功能一样,所有的shell的求值都是用整数完成$[]可以接受不同基数的数字[base#n]n表示基数从2到36的任何基数65*1.7输入和输出echoecho命令可以显示文本行或变量,或者把字符串输入到文件。echo[option]string-e解析转义字符-n回车不换行,linux系统默认回车换行转义符(\c,\f,\t,\n,\a)c不换行,f进纸,t跳格,n换行,a响铃。。。66*1.7输入和输出67*1.7输入和输出readread语句可以从键盘或文件的某一行文本中读入信息,并将其赋给一个变量。readvarible1varible2…如果只指定了一个变量,那么read将会把所有的输入赋给该变量,直到遇到第一个文件结束符或回车;如果给出了多个变量,它们按顺序分别被赋予不同的变量。Shell将用空格作为变量之间的分隔符。68*1.7输入和输出69*1.8表达式的比较shell程序中的test命令在bash/pdksh中,命令test用于计算一个条件表达式的值。他们经常在条件语句和循环语句中被用来判断某些条件是否满足。test命令的语法格式:testexpression

或者

[expression]70*1.8表达式的比较1.数字比较-eq比较两个数是否相等-ne比较两个数是否不等-gt比较一个数是否大于另一个数-ge比较一个数是否大于或是等于另一个数-lt比较一个数是否小于另一个数-le比较一个数是否小于或是等于另一个数71*1.8表达式的比较例72*1.8表达式的比较2.字符串比较=比较两个字符串是否相等,同则为“是”!=比较两个字符串是否不相等,不同则为“是”-z判断字符长度是否等于零,等于则为“是”

-n判断字符长度是否大于零,大于零则为“是”73*1.8表达式的比较示例代码74*1.8表达式的比较运行结果75*1.8表达式的比较3.文件操作符-e如果文件存在则为真-r确定是否对文件设置了读许可-w确定文件是否设置了写许可-x确定文件是否设置了执行许可-s确定文件是否具有大于零的长度-d确定文件是否为目录-f确定文件是否为普通文件-L

确定文件是否为符号连接文件76*1.8表达式的比较例77*1.8表达式的比较4.逻辑操作符逻辑操作符用来根据逻辑规则比较表达式。!,-a,-o字符表示NOT、AND和OR!求反(”非”)逻辑表达式-a逻辑AND(”与”)两个逻辑表达式-o逻辑OR(”或”)两个逻辑表达式78*1.8表达式的比较例79*1.9流程控制语句一、条件语句二、循环语句三、杂项语句80*1.9流程控制语句——一、条件语句一、条件语句1.if语句2.case语句81*1.9流程控制语句——一、条件语句1.if语句if语句通过判断逻辑表达式来作出选择,在bash中的条件语句有如下的格式:if[expression];thenstatementselif[expression];thenstatementselsestatementsfiif条件是可以嵌套的。82*1.9流程控制语句——一、条件语句2.case语句case语句是用来执行依赖于离散值或是匹配指定变量值的范围的语句。bash的case语句如下:casestrinstr1|str2)statements;;str3|str4)statements;;*)statements;;esac每个条件下用双分号(;;)来终止语句!83*1.9流程控制语句——一、条件语句84*1.9流程控制语句——二、循环语句循环语句:用于重复执行一系列命令。一)for语句二)until语句三)while语句四)select语句85*一)for语句1.第一种格式如下:for变量名in列表do命令1命令2⋯done当变量值在列表里,for循环即执行一次所有命令,使用变量名访问列表中取值。命令可为任何有效的shell命令和语句。变量名为任何单词。In列表用法是可选的,如果不用它,for循环使用命令行的位置参数。in列表可以包含替换、字符串和文件名.例如:86*一)for语句87*例:假设需要把目录中的每个文件在一个叫做backup的子目录中建立备份在bash中执行如下的程序:一)for语句88*一)for语句89*2.第二种格式如下:

forcurvardostatementsdone

在这种格式中,对传给shell程序的每个位置参数执行一次statements。对每次循环,把位置参数的当前值赋给变量curvar。记住$@提供传给shell程序的一系列参数,全部参数排在一起。这种格式也可以写成如下:forcurvarin“$@”do

statesmentsdone一)for语句90*一)for语句91*3.第三种格式:for((i=0;i<10;i++))doecho$idone一)for语句92*二)until语句用来执行一系列命令直到所指定的条件为真才能终止。在bash中,利用如下的格式:untilexpressiondostatementsdone93*1.9流程控制语句——二、循环语句3.while语句在bash中,利用的如下的格式:whileexpressiondostatementsdone94*1.9流程控制语句——二、循环语句例:求前五个偶数的和bash的shell程序如下:95*1.9流程控制语句——二、循环语句96*1.9流程控制语句——二、循环语句4.select语句select语句的格式如下:selectiteminitemlistdostatementsdoneitemlist是可选的,当未给出itemlist时,系统通过item中的项目一次重复一个,但当给出itemlist时,系统对itemlist中的每个项重复,对每次重复把itemlist的当前值赋给item,而后item可作为执行语句的一部分。97*1.9流程控制语句——二、循环语句如果编写一个提供用户挑选Continue或Finsh的选择菜单,则可编写如下的shell程序:

#!/bin/bashselectiteminContinueFinshdoif[$item=“Finsh”];thenbreakfidone

执行select命令时,系统向用户显示一个选择数字的菜单——在这种情况下:1表示Continue,2表示Finsh。当用户选择1时,变量item包含值Continue;而当用户选择2时,变量item包含值Finsh.。当用户选择2时,即执行if语句,并终止循环。98*1.9流程控制语句——三、杂项语句杂项语句:1.shift语句2.break语句3.exit语句99*1.9流程控制语句——三、杂项语句1.shift语句用来处理位置参数,并从左到右每次处理一个参数。应该记得,位置参数是用$1、$2、$3等来标识的。shift命令的作用时,把每个位置参数向左移动一个位置,而当前的$1丢失。shift命令的格式如下:shiftnumber参数number是移动的数目,是可选的。当不特别指定number时,缺省值为1,即参数向左移动一个位置。当指定number时,则向左移动number个位置。100*1.9流程控制语句——三、杂项语句101*1.9流程控制语句——三、杂项语句2.break语句用来终止重复执行的循环。break通常在进行一些处理后退出循环或case语句。如果是在一个嵌入循环里,可以指定跳出的循环个数。例如如果在两层循环内,用break2刚好跳出整个循环。3.continue语句它不会跳出循环,只是跳过这个循环步。102*1.10函数函数是shell程序中执行特殊过程的部件,并在shell程序中可以重复调用。下面是在bash中函数定义格式。func(){statements}可以调用函数如下:funcparam1param2param3参数param1param2等是可以选择的。还能把参数作为单字符串来传送,例如$@。函数可以分析参数,就好像它们是传送给shell程序的位置参数。103*1.10函数104*4.10函数105*1.10函数106*1.10函数107*1.10函数例:在传送月份数字后显示月份名或出错信息。displaymonth(){case$1in*)echo”Invalidparameter”esac}displaymonth8

程序显示如下:

MonthisAugust01|1)echo“MonthisJanuary”;;02|2)echo“MonthisFebruary”;;03|3)echo“MonthisMarch”;;04|4)echo“MonthisApril”;;05|5)echo“MonthisMay”;;06|6)echo“MonthisJune”;;07|7)echo“MonthisJuly”;;08|8)echo“MonthisAugust”;;09|9)echo“MonthisSeptember”;;10)echo“MonthisOctober”;;11)echo“MonthisNovember”;;12)echo“MonthisDecember”;;108*

Linux编程及应用

主讲:任继平邮箱:109*参考教材:linux软件工程师(C语言)实用教程110*课程要求:111*课程内容:112*第1章Linux系统程序设计基础113*第1章Linux系统程序设计基础114*本章重点编辑、编译及运行Linuxc程序gcc编译器的使用gdb调试器的使用115*1.1第一个Linuxc程序

例1-1:设计一个程序,要求在屏幕上输出“这是第一个Linuxc程序!”。步骤1:设计编辑源程序代码使用文本编辑器vim,在终端中输出:[root@localhostroot]#vim1-1.c

输入完成后存盘:按ESC键→输入“:wq”回车

116*1.1第一个Linuxc程序步骤2:编译程序查看当前目录下是否有1-1.c文件,输入命令:

[root@localhostroot]#ls1-1.c编译:[root@localhostroot]#gcc1-1.c-o1-1[root@localhostroot]#步骤3:运行程序[root@localhostroot]#ls1-1.c1-1[root@localhostroot]#./1-1这是第一个Linuxc程序!117*1.1第一个Linuxc程序Linux下的文本编辑器软件主要有vim、gedit和Emacs,Linux下的c编译器中,gcc是功能最强大、使用最广泛的软件。gcc编译的常用格式为:gccC源文件-o目标文件名或:gcc-o目标文件名C源文件或:gcc目标文件名最后一种情况目标文件名默认为:c.out118*1.1第一个Linuxc程序printf函数说明思考题:设计一个程序,要求在屏幕上输出:************119*1.2gcc编译器gcc是(GNUCmpilerCollection的简称),它是GNU项目中符合ANSIC标准的编译系统,能够编译用C、C++和ObjectC等语言编写的程序。gcc不仅功能十分强大,结构也异常灵活。它可以通过不同的前端模块来支持各种语言,如Java、Fortran、Pascal、Modula-3和Ada等。gcc是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比,平均效率要高20%~30%。gcc支持编译的后缀名:120*121*1.2.1使用gccgcc指令的一般格式为:gcc[参数]要编译的文件[参数][目标文件]例1-2:设计一个程序,要求把输入的百分制的成绩转换成五级制输出。即输入成绩大于等于90分,显示“优秀”;若成绩介于80~90分,显示“良好”;若成绩介于70~80分,显示“中等”;若成绩介于60~70分,显示“及格”;若成绩小于60分,显示“不及格”。 122*1.2.1使用gcc步骤1:编辑源程序代码

[root@localhostroot]#vim1-2.c123*1.2.1使用gcc步骤2:用gcc编译程序[root@localhostroot]#gcc1-2.c–o1-2步骤3:运行程序[root@localhostroot]#./1-2思考题:设计一个程序,要求输入一个数,如果此数大于0,显示“输入的为正数”,否则显示“输入的为负数”。124*1.2.2gcc编译流程125*1.2.2gcc编译流程例1-3:设计一个程序,要求输入两个整数,求和输出。通过使用gcc的参数,控制gcc的编译过程,了解gcc的编译过程,进一步认识gcc的灵活性。步骤1:编辑源程序代码[root@localhostroot]#vim1-3.c126*127*1.2.2gcc编译流程步骤2:预处理阶段[root@localhostroot]#gcc1-3.c–o1-3.i–E[root@localhostroot]#vim1-3.i步骤3:编译阶段[root@localhostroot]#gcc1-3.i–o1-3.s–S[root@localhostroot]#vim1-3.s步骤4:汇编阶段[root@localhostroot]#gcc1-3.s–o1-3.o–c128*1.2.2gcc编译流程步骤5:链接阶段Linux系统把printf和scanf函数的实现,都放在了libc.so.6的库文件中。在没有参数指定时,gcc到系统默认的路径“/usr/lib”下查找,链接到libc.so.6库函数中去,这样就有了printf和scanf函数的实现部分。把程序中一些函数的实现,这是链接阶段的工作。完成链接后,gcc就可以生成可执行程序文件

注意:gcc在编译的时候默认使用动态链接库,编译链接时并不把库文件的代码加入到可执行文件中,而是在程序执行的时候动态加载链接库,这样可以节省系统开销。129*1.2.2gcc编译流程scanf函数说明130*1.2.3gcc编译器的主要参数1.总体参数当头文件与gcc不在同一目录下要用-Idir编译,它是指头文件,而添加库文件时需用-Ldir参数。131*1.2.3gcc编译器的主要参数例1-4:设计一个程序,要求把输入的字符串原样输出,程序中的头文件自己定义,源程序文件为“1-4.c”,自定义的头文件为“my.h”,放在目录“/root”下。步骤1:设计编辑源程序代码1-4.c[root@localhostroot]#vim1-4.c132*1.2.3gcc编译器的主要参数步骤2:设计编辑自定义的头文件my.h[root@localhostroot]#vimmy.h步骤3:正常编译1-4.c文件:[root@localhostroot]#gcc1-4.c–o1-4编译器提示出错。133*注意:在include语句中,“<>”表示在默认路径“/usr/include”中搜索头文件,引号“”

””表示在本目录中搜索。因此,前面例子中把1-3.c中的“#include<my.h>”改成“#include“my.h””,就不需要“-Idir”参数也能正确编译了。步骤4:加“-Idir”参数编译:[root@localhostroot]#gcc1-4.c–o1-4–I/root134*1.2.3gcc编译器的主要参数getchar函数说明135*1.2.3gcc编译器的主要参数putchar函数说明思考题:此例能不能用前面的printf函数和scanf函数?如果可以,要如何改写程序?136*1.2.3gcc编译器的主要参数例1-5:有程序1-5.c用到目录“/root/lib”下的一个动态库libsunq.so。[root@localhostroot]#gcc1-5.c–o1-5.c–L/root/lib–lsunqLinux下的库文件命名时有一个规定:必须以l、i、b三个字母开头,因此,在用“-l”指定链接库文件时可以省去l、i、b三个字母。也就是说“-llibsunq”有时候写成“-lsunq”。 137*1.2.3gcc编译器的主要参数例1-6:设计一个程序,要求把输入的数字作为X轴坐标,算出它的sin值。步骤1:编辑源程序代码[root@localhostroot]#vim1-6.c138*1.2.3gcc编译器的主要参数步骤2:用gcc编译程序[root@localhostroot]#gcc1-6.c–o1-6结果发现编译器报错:原因是需要指定函数的具体路径,要查找函数sin,输入:[root@localhostroot]#nm-o/lib/*.so|grepsin139*1.2.3gcc编译器的主要参数在/lib/libm-2.3.2.so:00008610Wsin中除去函数库头lib及函数的版本号-2.3.2,所余下的符号为“m”,在编译时用字符“l”与余下的符号“m”相连接成“lm”,在编译时加上此参数就能正确地通过编译,即:[root@localhostroot]#gcc1-6.c–o1-6-lm步骤3:运行程序[root@localhostroot]#./1-6注意:Linux下动态链接库默认后缀名“.so”,静态链接库默认后缀名“.a”。140*1.2.3gcc编译器的主要参数gcc的常用告警和出错参数141*1.2.3gcc编译器的主要参数例1-7:设计一个程序,要求打印“这是一段用于测试的垃圾程序!”,里面包含一些非标准语法。步骤1:设计编辑源程序代码

[root@localhostroot]#vim1-7.c

142*步骤2:关闭所有告警[root@localhostroot]#gcc1-7.c–o1-7–w步骤3:显示不符合ANSIc标准语法的告警信息[root@localhostroot]#gcc1-7.c–o1-7–ansi步骤4:

允许发出ANSIc标准所列的全部警告信息[root@localhostroot]#gcc1-7.c–o1-7–pedantic步骤5:允许发出gcc提供的所有有用的告警信息[root@localhostroot]#gcc1-7.c–o1-7–Wall143*1.2.3gcc编译器的主要参数优化参数代码优化指的是编译器通过分析源代码,找出其中尚未达到最优的部分,然后对其重新进行组合,目的是改善程序的执行性能。gcc提供的代码优化功能非常强大,它通过编译参数“-On”来控制优化代码的生成,其中n是一个代表优化级别的整数。通常来说,数字越大优化的等级越高,同时也就意味着程序的运行速度越快。144*1.2.3gcc编译器的主要参数例1-8:设计一个程序,要求循环8亿次左右,每次都有一些可以优化的加减乘除运算。比较gcc的编译参数“-On”优化程序前后的运行速度。步骤1:编辑源程序代码:145*步骤2:不加任何优化参数进行编译。[root@localhostroot]#gcc1-8.c–o1-8步骤3:用time命令大致统计出该程序在运行时所需要的时间。[root@localhostroot]#time./1-8步骤4:加“-O2”优化参数进行编译。[root@localhostroot]#gcc1-8.c–o1-8–O2步骤5:再统计优化后的程序运行时所需要的时间。[root@localhostroot]#time./1-8步骤6:对比两次执行的输出结果。146*1.2.3gcc编译器的主要参数优化虽然能够给程序带来更好的执行性能,但在一些场合中应该避免优化代码。程序开发的时候。资源受限的时候。跟踪调试的时候。147*1.3gdb调试器1.gdb概述Linux下的gdb调试器,是一款GNU组织开发并发布的UNIX/Linux下的程序调试工具。它没有图形化的友好界面,但功能强大。在进行应用程序的调试之前,要注意的是gdb进行调试的是可执行文件,而不是如“.c”这样的源代码文件。因此,需要先通过gcc编译生成可执行文件才能用gdb进行调试。148*1.3gdb调试器2.使用gdb调试程序例1-9:设计一个程序,要求输入两个整数,判断并输出其中的最小数。步骤1:编辑源程序代码:

149*150*1.3gdb调试器步骤2:

用gcc编译程序[root@localhostroot]#gcc1-9.c–o1-9–g步骤3:

进入gdb调试环境[root@localhostroot]#gdb1-9注意:gdb是命令行调试环境,调试程序都在提示符“(gdb)”后输入相应的命令,gdb的命令很多,可以在提示符“(gdb)”后输入help进行查找。常用的gdb命令151*1.3gdb调试器步骤4:

用gdb调试程序(1)查看源文件在gdb中输入“l”(list)就可以查看程序源代码,一次显示10行;注意:gdb命令“l”(list)列出源代码的时候,要确保原来的源程序还在,如果读者以为这象反汇编一样给出代码,那就错了,其实只是列出源文件的内容。

特别提示:“list”+行号:查看指定位置的代码,如“list1”就是从第一行开始列出源代码。(2)设置断点在gdb中设置断点命令是“b”(break),后面跟行号或者函数名。如:(gdb)b10152*1.3gdb调试器(3)查看断点信息用命令“infob”(infobreak)查看断点信息。注意:gdb在一个程序中可以设置多个断点,有多个断点中断时,“Num”处显示断点序号。(4)运行程序:输入“r”(run)开始运行程序。注意:gdb默认从第一行开始运行,如果要从程序中指定行开始运行,只需输入“r”+行号。(5)查看变量值程序运行到断点处会自动暂停,输入“p变量名”153*1.3gdb调试器调试程序时,可能需要修改变量值,程序运行到断点处时,输入“set变量=设定值”,例如给变量“a2”赋值11,输入“seta2=11”。gdb在显示变量值时都会在对应值前加“$n”标记,它是当前变量值的引用标记,以后想再引用此变量,可以直接使用“$n”,提高了调试效率。注意:查看变量值,不能在程序结束后。154*(6)单步运行在断点处输入“n”(next)或者“s”(step)。它们之间的区别在于:若有函数调用时,“s”会进入该函数而“n”不会进入该函数。(7)继续运行程序输入“c”(continue)命令恢复程序的正常运行,把剩余的程序执行完,并显示执行结果。(8)退出gdb环境:输入“q”(quit)命令。思考题:此例中,如果比较的结果刚好相反,应该把断点设置在第几行?调试的时候还需要注意什么才能看出变量的值?155*思考与实验编写一个简单的c语言程序:输出两行文字“Linux下的c也不是太难嘛!”,在Linux下编辑、编译、运行。编写一个简单的c语言程序:根据输入的两个整数求平均值并且在终端输出,通过gcc编译器得到它的汇编程序文件。用gdb调试器调试上面第2题的程序,查看程序执行每一步变量的值,熟悉gdb的使用流程。编写一个c语言程序:打印输出所有“水仙花数”,用gdb调试程序(给出步骤,至少十步以上)。所谓“水仙花数”是指一个3位数,其各位数字立方和等于该数本身。例如,153是一水仙花数,因为153=1³+5³+3³。156*第2章文件分割和多文件编译157*本章重点函数编写与函数参数的传递多文件系统多文件系统中使用make使用autotools158*2.1函数函数指功能相对独立,由一系列语句组成的模块,它的目的有:当设计一个大型程序时,如果能够将这个程序依照功能,将其分割成较小的功能,然后依据这些小功能的要求编写函数,可以使程序简单化,同时也会使最后检查错误变得容易。在一个程序中,会产生指令重复使用多次的问题,将这些重复使用的指令编写成一个函数,需要时加以调用,可以提高编程效率,也可以使程序精简。159*2.1.1函数简介C语言函数可分为库函数和用户定义函数:库函数:由C系统提供,用户无须定义,也不必在程序中作类型说明,只需在程序前包含有该函数原型的头文件即可在程序中直接调用。用户自定义函数:由用户按需要编写的函数。对于用户自定义函数,不仅要在程序中定义函数本身,在很多情况下还必须对该函数进行原型说明,然后才能使用。160*2.1.1函数简介例2-1:设计一个程序,要求在屏幕上打印输出五行“Linux程序设计,有点意思!”的字符串。步骤1:编辑源程序代码;步骤2:用gcc编译程序[root@localhostroot]#gcc2-1.c–o2-1步骤3:运行程序[root@localhostroot]#./2-1161*2.1.1函数简介162*2.1.1函数简介在c语言中,所有的函数定义都是平行的。即在一个函数的函数体内,不能再定义另一个函数,。但是函数之间允许相互调用,也允许嵌套调用。习惯上把调用者称为主调函数。函数还可以自己调用自己,称为递归调用。函数的一般形式:函数类型函数名(形参类型:形式参数1,形参类型:形式参数2,……){类型说明;语句;}163*2.1.2返回值函数调用时,主调函数把实参的值传送给被调函数的形参,从而实现主调函数向被调函数的数据传送。函数调用中数据传送是单向的。即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。因此在函数调用过程中,形参的值发生改变,并不会影响到实参。函数运行结束,如果被调函数的结果需要传递回主调函数,通常用用return完成这项任务,叫函数的返回值。164*2.1.2返回值例2.2:设计一个程序,要求编写函数max,有两个参数,返回两个数中的最大值给主函数。步骤1:编辑源程序代码步骤2:用gcc编译程序

[root@localhostroot]#gcc2-2.c–o2-2步骤3:运行程序[root@localhostroot]#./2-2思考题:如果把此例中的数据传递改成指针传送,程序应该如何设计?165*166*2.2文件分割例2.3:设计一个程序,要求计算输入的整数的平均值,并将此程序分割成多个小文件。步骤1:编辑源程序代码167*168*2.2文件分割步骤2:分析程序、分割文件 将此程序分割成下列2个Linuxc程序。 (1)2-3-main.c为主程序:

(2)2-3-avg.c为avg函数的定义:步骤3:用gcc编译程序[root@localhostroot]#gcc2-3-main.c2-3-avg.c–o2-3步骤4:运行程序[root@localhostroot]#./2-3169*170*2.2文件分割Linuxc文件分割,主要是把每个自定义函数分割成独立的c源程序文件,自定义函数的声明部分需要包含在主调函数中,这儿的主调函数是main。如果自定义函数较多,也可以把函数声明都分割成独立的头文件,在主调函数中用#include包含分割出来的头文件。思考题:如何把自定义函数的声明部分,也分割成独立的文件,分割后如何编译?171*2.2文件分割例2.4:分割例2-2中的程序,要求分割后自定义函数在另一个独立的文件中。步骤1:分析程序、分割文件例2-2程序有主函数main和自定义函数max,再把函数声明都分割成独立的头文件,可将此程序分割成下列3个文件。(1)2-4-main.c为主程序:(2)2-4-max.c为max函数的定义

:(3)max.h为头文件,内含max函数的声明:172*2.2文件分割173*2.2文件分割步骤2:用gcc编译程序

[root@localhostroot]#gcc2-4-main.c2-4-max.c–o2-4步骤3:运行程序[root@localhostroot]#./2-4思考题:能否将此例中的#include"max.h"修改成#include<max.h>,为什么?174*2.3make工程管理器make工程管理器是一个“自动编译管理器”,这里的“自动”是指它能够根据文件时间戳自动发现更新过的文件而减少编译的工作量,同时,它通过读入makefile文件的内容来执行大量的编译工作。用户只需编写一次简单的编译语句就可以了。它大大的提高了实际的工作效率。175*2.3.1编写makefile文件在一个Makefile文件中通常包含如下内容:需要由make工具创建的目标体(target),通常是目标文件或可执行文件。要创建的目标所依赖的文件。创建每个目标体时需要运行的命令。176*2.3.1编写makefile文件例2.5:设计一个程序,要求计算学生的总成绩和平均成绩,并用make工程管理器编译。步骤1:分析程序、分割文件此程序有主函数main和自定义函数fun_sum和fun_avg,再把函数声明都分割成独立的头文件,可将此程序分割成下列4个文件。(1)2-5-main.c为主程序: (2)chengji.h为头文件,内含fun_avg和fun_sum函数的声明:177*2.3.1编写makefile文件(3)2-5-fun_sum.c为fun_sum函数的定义:(4)2-5-fun_avg.c为fun_avg函数的定义:178*2.3.1编写makefile文件179*2.3.1编写makefile文件步骤2:编辑makefile文件[root@localhostroot]#vimmake

makefile内容:步骤3:用make命令编译程序[root@localhostroot]#make–fmake步骤4:

用make命令再次编译修改4个文件中的一个,重新用make编译,会发现只编译了2-5-main.c程序,另外的2个c源程序文件根本没有重新编译。步骤5:运行程序[root@localhostroot]#./2-5180*从结果来看,在没有使用gcc编译器命令情况下,依然把设计的程序编译成了可执行文件,实现了设计的功能,可见make工程管理器调用了gcc编译器,makefile文件的编写是重点。181*2.3.2makefile变量的使用例2.6:设计一个程序,程序运行时从三道题目中随机抽取一道,题目存放在二维数组中。步骤1:分析程序、分割文件此程序有主函数main和自定义函数fun_shuiji,可以分割成两个“.c”程序文件;再把函数声明和用到的库函数的头文件,分割到一个独立的自定义头文件“shuiji.h”;因此,可将此程序分割成3个文件。(1)2-6-main.c为主程序(2)shuiji.h为头文件(3)2-6-fun_sum.c文件182*183*184*2.3.2makefile变量的使用步骤2:编辑makefile文件[root@localhostroot]#vimmake一般的makefile写法:使用变量的makefile写法如下:

步骤3:用make命令编译程序[root@localhostroot]#make–fmake

步骤4:运行程序[root@localhostroot]#./2-6185*186*2.3.2makefile变量的使用Makefile中常见预定义变量187*2.3.2makefile变量的使用Makefile中常见自动变量思考题:如果此例的题目数、题目内容以及随机抽取的题目量,都由用户决定,应该如何修改程序?makefile文件要不要修改?188*2.3.3make和makefilemakefile文件主要包含了5部分内容:显式规则。说明了如何生成一个或多个目标文件。由makefile文件的创作者指出,包括要生成的文件、文件的依赖文件、生成的命令。隐式规则。由于make有自动推导的功能,所以隐式的规则可以比较粗糙地简略书写makefile文件,这是由make所支持的。189*3.变量定义。在makefile文件中要定义一系列的变量,变量一般都是字符串,这与C语言中的宏有些类似。当makefile文件执行时,其中的变量都会扩展到相应的引用位置上。190*2.3.3make和makefile文件指示。其包括3个部分,一个是在一个makefile文件中引用另一个makefile文件;另一个是指根据某些情况指定makefile文件中的有效部分;还有就是定义一个多行的命令。注释。makefile文件中只有行注释,其注释用“#”字符。如果要在makefile文件中使用“#”字符,可以用反斜框进行转义,如:“\#”。191*2.3.3make和makefileGNU的make工作时的执行步骤:读入所有的makefile文件。读入被include包括的其他makefile文件。初始化文件中的变量。推导隐式规则,并分析所有规则。为所有的目标文件创建依赖关系链。根据依赖关系,决定哪些目标要重新生成。执行生成命令。

192*2.4autotools的使用autotools工具只需用户输入简单的目标文件、依赖文件、文件目录等就可以轻松地生成makefile了。可以完成系统配置信息的收集,从而可以方便地处理各种移植性的问题。autotools是系列工具,包含有:aclocalautoscanautoconfautoheaderautomake193*2.4autotools的使用用autotools产生Makefile文件的总体流程194*2.4autotools的使用利用autotools系列工具生成“Makefile”文件的基本步骤:195*2.4autotools的使用例2.7:利用例2.3中的两个程序文件“2-3-main.c”和“2-3-avg.c”,把它们的文件名分别改成“2.7.main.c”和“2.7.avg.c”,用autotools工具生成makefile文件。步骤1:

使用autoscan。196*2.4autotools的使用步骤2:

修改“configure.scan”文件,重命名成“configure.in”文件修改时需要增加一个宏AM_INIT_AUTOMAKE(PACKAGE,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论