linux实训

目  录

Unit 1 操作系统安装.... 3

1.1 多操作系统安装... 3

1.1.1 VMware简介... 3

1.1.2 VMWare基本使用... 4

1.2 安装Red Hat Linux 9.0. 15

1.3 思考题... 15

【实习报告】... 16

Unit 2  Linux命令接口使用.... 17

2.1 访问Linux系统... 17

2.1.1 创建用户组... 17

2.1.2 删除用户组... 17

2.1.3 创建用户... 18

2.1.4 删除用户... 19

2.2 Linux文件信息命令和基本文件管理... 20

2.3 Linux文件权限... 20

2.3.1 文件权限... 20

2.3.2 设置文件权限... 21

2.3.3 设置文件的拥有权... 22

2.4 思考题... 23

【实习报告】... 25

Unit 3  Linux vi的使用.... 52

3.1 vi的启动与退出... 52

3.2 光标移动... 53

3.3 编辑操作... 54

3.4 查询操作... 56

【实习报告】... 57

Unit 4  Linux shell编程.... 59

4.1 shell编程简介... 59

4.1.1 shell程序文件... 59

4.1.2 shell程序的建立... 60

4.1.3 shell程序的运行... 61

4.1.4 shell变量... 63

4.1.5 shell程序的控制流... 65

4.2 shell程序调试简介... 68

4.3 实例... 69

【实习报告】... 80

Unit5  Linux C编程.... 82

5.1 程序的编辑与编译... 82

5.2 程序的调试... 83

5.2.1 gdb简介... 83

5.2.2 调试实例... 84

5.3 程序与OS间的参数传递... 87

【实习报告】... 89

Unit6  Linux设备编程.... 90

6.1 Linux声音设备编程... 90

6.2 Linux扬声器编程的应用... 90

6.3 软盘使用... 92

6.4 U盘使用... 92

【实习报告】... 93

Unit7  Linux并发程序设计.... 94

7.1 Linux进程控制... 94

7.1.1 进程的创建... 95

7.1.2 进程的运行... 96

7.1.3 进程的终止... 98

7.1.4 进程的同步... 99

7.1.5 进程挂起... 100

7.2 Linux进程通信... 101

7.3 Linux重定向和管道... 105

7.4 管理Linux系统进程... 105

7.5 思考题... 106

【实习报告】... 107

可选练习... 114


Unit 1 操作系统安装

【实习要求】

1、掌握多操作系统的安装方法

2、掌握Linux的安装方法

【实习内容】

1、安装Red Hat Linux 9.0

1.1 多操作系统安装

1.1.1 VMware简介

VMWare Workstation是一个“虚拟PC”软件。它使你可以在一台机器上同时运行两个或多个操作系统,如Windows、DOS、Linux等。与“多启动”系统相比,VMWare采用了完全不同的概念。多启动系统在一个时刻只能运行一个系统,在系统切换时需要重新启动机器。VMWare是真正“同时”运行多个操作系统在主系统的平台上,它就象标准Windows应用程序那样切换。而且每个操作系统你都可以进行虚拟的分区、配置而不影响真实硬盘的数据,你甚至可以通过网卡将几台虚拟机用网卡连接为一个局域网,极其方便。它为操作系统,或网络实习提供了极好的运行平台环境。

1、虚拟机(VM)

VM――Virtual Machine,虚拟机是指运行于宿主机系统中的虚拟系统,该系统模拟了物理计算机的硬件控制模式,具备有运行于物理计算机硬件上系统的大部分功能,以及物理计算机不具备的部分扩展功能。

2、宿主机与客户机

宿主机即物理计算机。

客户机即运行于虚拟机软件中的系统。

3、常用虚拟机软件

常用支持宿主机系统为:Windows 98/Windows 2k/Windows XP/VISTA/Linux的虚拟机软件有:

(1)VMware Workstation(英文版)

注册:共享版,有使用期限,需要官方授权,网上有注册机。

(2)Virtual PC(英文版)

注册:共享版,有使用期限。

(3)Parallels Workstation(英文版)

注册:试用版,有使用期限,需要官方授权,网上有注册机。

(4)VirtualBox(多国语言——中文版)

注册:免费版本,无需注册。

(5)QEMU(中文版)

注册:免费版本,无需注册。

1.1.2 VMWare基本使用

下面以VMware Workstation 6.0.1 for Windows(英文版)为例,简要说明利用虚拟机软件创建虚拟系统,并进行虚拟机系统安装的基本过程。

1、菜单栏介绍

(1)File

主要管理虚拟机在宿主机中的文件,具体命令项如下:

l  New:新建虚拟机/组/窗口。

l  Open:打开存在的虚拟机文件。

l  Import:导入其他支持的类型文件,转换为VMware的虚拟机文件格式,例如Virtual PC的虚拟机文件。

l  Close:关闭当前打开的虚拟机。

l  Map or Disconnect Virtual Disks…:将支持类型的虚拟机文件映射为一个硬盘,或取消映射。

l  Remove from Favorites:从左侧收藏夹中删除,不会影响磁盘中文件。

l  Exit:退出。

(2)Edit

编辑虚拟机全局设置和控制菜单,具体命令项如下:

l  Cut:剪切。

l  Copy:复制。

l  Paste:粘贴。

l  Virtual Network Settings…:设置虚拟机与宿主机网络连接方式。

l  Preferences…:设置虚拟机选项参数。

(3)View

查看虚拟机和客户机选项,具体命令项如下:

l  Full Screen:全屏,使当前虚拟机屏幕覆盖宿主机屏幕。

l  Quick Switch:快速切换,当打开多个客户机时,进行快速切换。

l  Current View:当前查看。

l  Autofit Window:自动匹配窗口,使客户机窗口自动匹配虚拟机窗口,需安装VMware tools。

l  Autofit Guest:自动匹配客户机,使虚拟机自动匹配窗口客户机窗口,需安装VMware tools。

l  Fit Window Now:立即匹配窗口,立即使客户机窗口匹配虚拟机窗口,需安装VMware tools。

l  Fit Guest Now:立即匹配客户机,立即使虚拟机匹配窗口客户机窗口,需安装VMware tools。

l  Go to Home Tab:转到主页。

l  Sidebar:边栏。

l  Toolbars:工具栏。

l  Status Bar:状态栏。

l  Tabs:标签。

(4)VM

虚拟机,具体命令项如下。

l  Power:电源,当前客户机电源开关。

l  Removable Devices:可移动设备,管理连接到客户机的可移动设备,如U盘等。

l  Snapshot:快照,创建、管理或恢复快照,创建快照即记录当前客户机的状态,恢复快照即恢复到创建快照时的状态。

l  Replay:重放,重放虚拟机记录的操作,需开启客户机设置中允许重放设置。

l  Clone:克隆,创建客户机当前状态的克隆,比完全复制节省时间和磁盘空间,并且可避免网络冲突。

l  Install VMware Tools…:安装VMware工具…,VMware Tools提供了显示和性能的优化和控制的方便。

l  Upgrade or Change version:升级,升级虚拟机软件。

l  Connected Users:已连接用户,虚拟机客户机当前远程控制的用户。

l  Send Ctrl+Alt+Del:发送Ctrl+Alt+Del,在客户机中发送Ctrl+Alt+Del。

l  Grab Input:抓获输入,保持鼠标和键盘等输入设备在客户机中有效。

l  Capture Screen…:捕获屏幕…,捕获当前客户机屏幕显示,即截屏。

l  Capture Movie…:捕获影片…,动态捕捉当前客户机屏幕显示,将在宿主机中保存为影片。

l  Delete from Disk:从磁盘删除,从宿主机磁盘中删除虚拟机文件,不可恢复。

l  Message Log:消息日志,事件日志,可协助解决虚拟机设置不正确问题。

l  Settings…:设置…,当前客户机相关选项。

(5)Team

将多个客户机合并为一组以方便网络通信是组的作用,具体命令项如下:

l  Power:组电源,控制当前组所有客户机的总电源。

l  Switch to:转到组中指定客户机。

l  Add:增加新的客户机成员到本组。

l  Remove:移除本组中指定客户机,该客户机文件不会在宿主机磁盘中删除。

l  Delete from Disk:从磁盘中删除组配置文件,解散组,不会删除该组中客户机的文件。

l  Settings…:组选项设置。

l  Windows:客户机窗口切换。

l  Home:主页。

l  Next Window:下一窗口。

l  Previous Window:前一窗口。

(5)Help

帮助。

2VMware Workstation使用实例

实例中宿主机与客户机系统说明如下:

宿主机系统为:

l  Windows XP with SP2 简体中文专业版

客户机系统分别为:

l  Red Hat Linux 9.0(红帽子Linux 9.0 简体中文版)

l  Windows Server 2003 R2 with SP2 简体中文企业版

l  Windows XP with SP2 简体中文专业版

步骤如下:

(1)创建新的客户机,点击菜单命令“File/New/Virtual Machine”,如图1-1。

图1-1

(2)出现如图1-2所示的“New Virtual Machine Wizard”对话框,点击“下一步”。

图1-2

(3)出现如图1-3所示对话话,选中“Typical”项,再点击“下一步”。

注:如选择“Custom”项,则可以选择制作与VMware Workstation 6.0之前版本以及VMware ACE等软件兼容的虚拟机,供其使用,或仅制作能供VMware Workstation 6.0之后版本软件使用的虚拟机。以及内存等其他选项的自定义。

(4)出现如图1-4所示的对话框窗口,选择客户机将使用的操作系统。我们将安装Windows XP,选择Microsoft Windows,同时在Version下拉菜单中选择Windows XP Professional 。点击“下一步”。

图1-3

图1-4

(5)出现如图1-5所示的对话框窗口,定义客户机的名称,以及对应客户机文件在宿主机磁盘中的存放位置。保持默认,点击“下一步”。

图1-5

(6)出现如图1-6所示的对话框窗口,选择网络访问模式。这个需要注意一下,选择“Use bridged networking”或“Use network address translation(NAT)”,点击“下一步”。

注:

Use bridged networking:使用桥接

Use network address translation(NAT):使用网络地址转换

Use host-only networking:仅和主机相连

Do not use a network connection:不使用网络连接

(7)出现如图1-7所示的对话框窗口,定义虚拟机最大硬盘容量。保持默认,点击“完成”。

图1-6

图1-7

(8)至此,虚拟机客户机创建完成,如图1-8所示。接下来,将在这个客户机中安装操作系统。

图1-8

(9)在进行客户机系统安装前,要做一些准备。如图1-9所示,对虚拟机设备进行设置,具体有:

Memory

Hard Disk

CD-ROM

Floppy

USB Controller

Sound Adapter

Display

Processors

然后,在客户机的光驱中放入安装系统的光盘,在此使用的是深度论坛的Windows XP Ghost 安装光盘5.0版作为安装Windows XP实例。

图1-9

(10)在安装操作系统前,须对客户机硬盘进行分区,然后才能进行安装,需要提醒注意的是系统盘分区必须设置为活动,如图1-10中状态必须为“作用”,否则系统无法正确引导。

图1-10

(11)图1-11为Ghost快速恢复过程,即恢复Windows XP。建议学生利用虚拟机练习Windows XP安装。

图1-11

(12)系统安装完成后,进入系统如图1-12。注意最底下状态栏中出现警示“VMware tools is not installed in this guest.……”,即系统提示未安装VMware tools。在这种状态下,无法快速调整客户机屏幕大小,鼠标键盘进入客户机后,无法移出到宿主机,而必须按热键“Ctrl+Alt”才能释放鼠标和键盘输入。

(13)点击菜单命令“VM/Install VMware tools...”,如图1-13所示,安装VMware tools。安装完成要求重新启动客户机。

(14)重新启动客户机后,如图1-14所示,状态栏不再出现警示。此时,客户机窗口大小可以随意调整了,鼠标也可以在客户机和宿主机之间自由移动。现在使用客户机就像我们在Windows中使用一般应用程序那样方便了。

至此客户机系统部署完成,我们能像使用宿主机一样使用客户机了。

图1-12

图1-13

图1-14

1.2 安装Red Hat Linux 9.0

【实习报告】

实习报告:操作系统安装

一、实习内容

1、安装Red Hat Linux 9.0

二、实习总结

 

Unit 2  Linux命令接口使用

【实习要求】

1、掌握Linux系统访问的常用命令

2、掌握Linux文件的基本操作

3、了解Linux系统结构

【实习内容】

1、访问Linux系统

2、Linux文件信息命令和基本文件管理

3、Linux文件权限

【实习指导】

2.1 访问Linux系统

2.1.1 创建用户组

创建用户组可使用命令groupadd来实现,下面介绍groupadd命令的基本使用。

格式:

groupadd  <组名>

功能:创建由<组名>指定的用户组。

例如,要求新建一名为“group1”的用户组,方法如下:

(1)以超级用户身份登录系统。

(2)创建用户组“group1”,键入命令“groupadd  group1”。

(3)检查用户组“group1”是否已成功创建,键入命令“cat /etc/group | more”,可观察到名为“group1”的用户组已创建。

2.1.2 删除用户组

当一用户组不再需要时,应将其删除。但要注意:如果要删除的组是当前登录的某个用户的基本组,则不可删除。另外,若要删除某一组,则应将系统中属于该用户组的文件和目录改为其他的组,然后再删除它。删除用户组可使用命令groupdel来实现,下面介绍groupdel命令的基本使用。

格式:

groupdel  <组名>

功能:

删除由<组名>指定的用户组。

例如,要求将名为“group1”的用户组删除,方法如下:

(1)以超级用户身份登录系统。

(2)删除用户组“group1”,键入命令“groupdel  group1”。

(3)检查用户组“group1”是否已成功删除,键入命令“cat  /etc/group | more”,可观察到名为“group1”的用户组已不存在。

2.1.3 创建用户

Linux系统中,除超级用户root是在安装时由系统创建外,其余用户均由超级用户创建。所谓创建用户,即为一新用户创建登录系统的账号,包括创建用户名和设置该用户的口令。创建用户名可使用命令“useradd”来实现,设置用户口令可使用命令“passwd”来实现。下面分别介绍命令“useradd”和“passwd”的基本使用。

1useradd命令

格式:

useradd  [-g  <组名>] [-d  <用户工作目录>] <用户名>

功能:创建由<用户名>指定的新用户,且产生一个该用户所独立拥有的用户工作目录。

选项说明:

-g  <组名>:<组名>指定了新用户所属的组(注意,该组必须已经存在)。当选项-g缺省时,则新建用户所属组名与用户名相同。

-d  <用户工作目录>:<用户工作目录>指定了新用户所独立拥有的工作目录的位置(注意:该目录必须已存在)。当选项-d缺省时,则新建用户所独立拥有的工作目录位于/home下。

2passwd命令

格式:

passwd  [用户名]

功能:对由“用户名”指定的用户创建或修改口令。注意:当“用户名”缺省时,是对当前用户修改口令。超级用户能创建和修改所有用户的口令,而普通用户只能修改自己的口令。

例如,要求创建一用户名为“user1”,口令为“123”的新用户,且该用户所属组的组名为“group”,实现方法如下:

(1)用超级用户身份登录系统。

(2)建立用户组“group”,键入命令“groupadd  group”。

(3)建立属于用户组“group”的新用户“user1”,键入命令“useradd  -g  group  user1”。

(4)设置用户“user1”的口令,键入命令“passwd  user1”,在系统提示下,输入口令“123”二遍。

(5)检查用户“user1”是否成功创建,键入命令“ls  -l  /home”,可观察到如图2-1所示信息,说明属于“group”组的用户“user1”已建立。

图2-1

例如,要求创建一用户名为“user2”,口令为“456”的新用户,且该用户属于组 “user2”。实现方法如下:

(1)以超级用户身份登录系统。

(2)建立用户组“group”,键入命令“groupadd  user2”。

(3)创建属于“user2”组的新用户“user2”,键入命令“useradd  -g user2  user2”。

(4)设置用户“user2”的口令,键入命令“passwd  user2”,在系统提示下,输入口令“456”二遍。

(5)检查用户“user2”是否成功创建,键入命令“ls  -l  /home”,可观察到如图2-2所示信息,说明属于“user2”组的用户“user2”已建立。

图2-2

2.1.4 删除用户

当确定一用户已不再需要时,应将其删除。由于系统中的所有普通用户均由超级用户创建,所以用户的删除亦只能由超级用户来完成。删除用户可使用命令userdel来实现。下面介绍命令userdel的基本使用。

格式:

userdel  [-r]  <用户名>

功能:

删除由“用户名”指定的用户,即在“/etc/passwd”文件中将该用户信息删除。

选项说明:

-r:在删除用户信息的同时,将该用户的工作目录删除,即将该用户完全删除。缺省时仅删除“/etc/passwd”文件中的用户信息。

例如,要求将名为“user2”的用户完全删除。实现方法如下:

(1)以超级用户的身份登录。

(2)完全删除用户“user2”,键入命令“userdel  -r  user2”。

(3)检查用户“user2”是否成功删除,首先键入命令“cat  /etc/group |more”,可观察到用户“user2”的信息已不存在,然后键入命令“ls  -l  /home”,可观察到用户“user2”的工作目录已不存在,说明用户“user2”已完全删除。

2.2 Linux文件信息命令和基本文件管理

2.3 Linux文件权限

2.3.1 文件权限

Linux系统将所有可设置权限的用户分成文件主(即文件拥有者)、同组用户和其他用户三种类别。

Linux系统对文件和目录提供了r、w、x三种权限,但文件的权限和目录的权限的含义是有所不同的,表2-3-1列出了三种权限用于文件和用于目录时的意义。

2-3-1  Linux文件系统权限的意义

权限

用于目录时的意义

用于文件时的意义

x

允许用户进入目录。只有拥有了“x”权限,下面介绍的“r”和“w”权限才有意义。

允许执行文件。

r

允许显示目录中文件和目录,但对该目录还必须有“x”权限。

允许显示文件内容。

w

允许在目录中创建、删除、改名目录和文件,但对该目录还必须有“x”权限。

允许改变文件内容。

此外,需要强调的是,在Linux中对普通文件的访问权限还依赖于目录文件的访问权限。例如,一用户对指定路径下的文件虽然拥有写访问权限,但该用户并不一定对此文件就能够写访问,只有当该用户对此文件的访问路径上包含的所有目录至少拥有“r-x”权限时,才真正能够对该文件写访问。

通过命令“ls  –l”,可查看文件或目录的权限,命令列出的第一栏的十位字符中包含了文件类型和文件权限,现将第一栏十位字符的意义说明如下(其中X表示每一位字符):

X

X X X

X X X

X X X

Linux提供的常见文件类型有:

-:文件。

d:目录。

十位字符中,除第一位表示文件类型外,其余九位表示文件的权限,三位一组分成三组,依次代表文件主、同组用户以及其他用户的三类不同用户,每组中的三位,依次表示r、w、x权限。当对应的位置不显示为“-”时,表示该类用户对此文件拥有相应的权限,反之,若对应的位置显示为“-”时,则表示该类用户对此文件不拥有相应的权限。例如,用户的权限为“-rwxr-xr--”,则表示文件的用户主对该文件拥有读、写和执行的权限,同组用户对该文件则拥有读和执行的权限,但不拥有写的权限,其他用户对该文件只拥有读的权限。在系统内部,这十位信息是用十位二进制来保存的。

2.3.2 设置文件权限

Linux提供了设置文件权限的一组命令,修改文件权限命令chmod,但这一命令只有文件主和超级用户可以使用。下面介绍chmod命令的基本使用。

格式一:chmod  {a,u,g,o} {+,-,=} {r,w,x}   <文件名>

格式二:chmod  nnn  <文件名>

功能:格式一是用字符r、w、x形式对由“文件名”指定的普通文件或目录文件,向各用户设置访问权限。格式二是用nnn三位八进制数形式对由“文件名”指定的普通文件或目录文件,为各用户设置访问权限。

说明:

{a,u,g,o}:表示向由a,u,g,o指定的用户设置文件的权限,各自的意义是,“a”表示所有用户;“u”表示文件主;“g”表示同组用户;“o”表示其他用户。

{+,-,=}:表示操作符,各自的意义是,“+”表示增加权限;“-”表示删除权限;“=”表示赋予权限,即使“文件名”指定的文件或目录只具有指定的权限。

{r,w,x}:表示读、写、执行权限。

nnn:三位八进制数依次对应于文件主、同组用户和其他用户的权限。三位数字中的每一位对应各权限之和如下:

---

0

--x

1

-w-

2

-wx

3

r--

4

r-x

5

Rw-

6

rwx

7

例如,若nnn的值为“754”,则对应的权限字符形式为“rwxr-xr--”,表示文件的用户主对文件拥有读、写和执行的权限;同组用户对该文件则拥有读和执行权限,但不拥有写的权限;其他用户对该文件则只拥有读的权限。

例如,要求将文件junk的读访问权限赋予所有用户,则以超级用户或文件主身份登录系统,在shell提示符下,键入命令“chmod  a+r  junk”。

例如,要求对文件junk,删除所有者以外的所有用户的读访问权限,则在shell提示符下,键入命令“chmod  og-r  junk”。

例如,要求文件junk,除文件主具有读、写、执行权限外,其他所有用户只拥有读访问权限。

方法一:

在shell提示符下,键入命令“chmod  u + rwx,go = r  junk”。

方法二:

在shell提示符下,键入命令“chmod  744  junk”。

例如,要求将文件junk的读、写、执行权限赋予所有用户。

方法一:

在shell提示符下,键入命令“chmod  a+rwx  junk”。

方法二:

在shell提示符下,键入命令:“chmod  777  junk”。

例如,要求撤消文件junk对其他用户已开放的所有权限。

在shell提示符下,键入命令“chmod  o=  junk”。

2.3.3 设置文件的拥有权

用户除了可为文件或目录设置访问权限外,还可以更改文件或目录的主和组,即用户可将原来属于自己的文件或目录转给他人。

1、更改文件和目录所属的主

chown命令可用来改变文件和目录所属的主,下面介绍chown命令的基本使用。

格式一:chown  [ -R ]  <用户名>  <文件/目录>

格式二:chown  [ -R ]  <用户名:组名>  <文件/目录>

说明:格式一是将“文件/目录”指定的文件或目录的拥有者更改为“用户名”所指定的用户。格式二是将“文件/目录”指定的文件或目录的拥有者更改为“用户名”所指定的用户,且同时将文件或目录的所属的组更改为“组名”所指定的组。

选项说明:

-R:改变整个目录。

2、更改文件和目录所属的组

如果要改变文件或目录所属的组,则可用命令chgrp来实现,下面介绍chgrp命令的基本使用。

格式:

chgrp  <组名>  <文件/目录>

说明:将“文件/目录”指定的文件或目录所属的组更改为“组名”所指定的组。

选项说明:

-R:改变整个目录。

例如,在目录“/home/user1”下,有一名为“myfile”的文件,文件的拥有者是“user1”,文件所属的组是“user1”,现要求将该文件的拥有者改为“user2”,文件所属的组更改为“user2”(假定用户user2和用户组user2均已存在),更改文件的拥有者和属组的方法如下:

(1)以root身份登录。

(2)键入命令“chmod  user2  /home/user1/myfile”。

(3)键入命令“chgrp  user2  /home/user1/myfile”。

或将(2)和(3)用命令“chmod  user2:user2  /home/user1/myfile”来完成。

2.4 思考题

1、如何实现普通用户与超级用户间的转换?

2、使用命令shutdown,实现Linux的关闭与重启

(1)五分钟以后,关闭系统

(2)十五分钟以后,关闭系统,并且在关闭后重新启动系统

3、Linux文件与目录

(1)用一条命令实现,列出 /home子目录下的所有文件和子目录(包括下级子目录中的文件和子目录)的详细信息。

(2)用一条命令实现,列出 以/home为起点的子树中所有小写字母开头的文件的详细信息。

(3)要求在用户工作目录 /home下,创建下图所示的目录树(其中,文件的内容自定),在建立过程中,要求:

① 用一条命令,实现在teachear目录下,建立子目录/a~/z

② 用一条命令,实现同时建立父子目录student和stu1

③ 用一条命令,实现删除目录teacher

 

 /

user

  /student

/teacher

 /other

     /stu1

 /a

 /b

   ……

 /z  file1

file2

file3

(4)显示以目录user为起点的目录树图形结构。

(5)用一条命令,实现显示目录 /etc下的所有文件和目录,且通过特定的后缀字符,区分出目录和文件及隐含文件、普通文件等信息。

(6)父目录、子目录及孙子目录能否用一条命令同时建立?

(7)比较rmdir、rm命令,在删除目录功能上的区别。

(8)用命令more浏览ux内核文件 /usr/src/Linux/kernel/signal.c的内容,并搜寻其中“if”字符串。

4、Linux文件权限

(1)Linux中,将可设置文件权限的用户分成哪几种?Linux向他们提供了哪些可设置权限?

(2)如何实现Linux的文件权限的修改?在修改时要注意什么?

(3)在当前目录下创建文件ex1,然后用chmod命令的二种格式分别修改ex1的文件权限,权限修改为:文件主享有所有权限,同组用户和其他用户享有读权限和执行权限。

(4)分析总结文件与目录权限的依赖关系。

(5)写出下面三位八进制数的权限意义及对应的字符形式的权限表示。

     777、644、755、750、770

【实习报告】

实习报告:Linux命令接口使用

学生姓名:       班级:        学号:

一、实习内容

1、访问Linux系统

    1. 登录规则和口令规则

(1) 列举至少2条Linux登录ID的规则或者要求。

1) __________________________________________________________________

2) __________________________________________________________________

3) __________________________________________________________________

(2) 列举至少3条Linux口令的规则或者要求。

1) __________________________________________________________________

2) __________________________________________________________________

3) __________________________________________________________________

4) __________________________________________________________________

    2. 登录Linux

获取用户名和口令,在带有GNOME登录界面的Linux工作站上执行以下步骤完成本实验环节:

步骤1:开机,启动Red Hat Linux系统,在系统登录界面的左下方单击“会话”,在屏幕上弹出的菜单中选择会话方式,我们选择“GNOME”,单击“确定”按钮。

步骤2:使用分配的用户名登录。将这个用户名输入在欢迎界面的“用户”输入框中,回车后再输入分配的口令并回车。系统显示Red Hat Linux桌面。

步骤3:单击屏幕左下方的红帽子,在菜单中单击“系统工具”-“终端”命令,显示“终端”窗口。

步骤4:在命令行提示符 ($) 下输入更改口令的命令。应该输入的命令是什么?

_________________________________________________________________

步骤5:系统提示:(current) UNIX password: ,输入当前密码 (注意区分大小写) 。

步骤6:系统接着提示:New password,输入新的密码abc。是否能够把密码改为abc?说出为什么能够或者为什么不能改?

_________________________________________________________________

步骤7:当再次出现提示符的时候,输入另外一个密码abcdef。能够把密码改为abcdef吗?说出为什么能够或者为什么不能改?

_________________________________________________________________

步骤8:输入新的密码Linuxl23。

步骤9:重新输入确认密码。确认后收到了什么信息?

_________________________________________________________________

步骤10:在命令行提示符 ($) 下键入Exit或者按下Ctrl和D键,关闭终端视窗。

     3. Linux系统中的Shell

在提示符下 (例如 $ ) 输入:echo $SHELL并按回车键即可找出当前系统所使用的Shell。

_________________________________________________________________

如果更改系统的Shell,建议考虑bash,因为它的功能最强大,并且符合POSIX标准,而且在Linux上非常的流行。使用chsh命令可改变所使用的Shell。

    4. Linux系统中文件与目录

我们来了解Linux通配符的使用。

首先假设当前目录下有五个文件 (inv1jig.c、inv2jig.c、inv3jig.c、invinitjig.c、invpar.c) ,然后执行操作:

       $ ls inv?jig.c

使用此命令将列出文件名中第四个字符包含数字的文件,结果包括:

_________________________________________________________________

执行操作:

       $ ls inv[13]jig.c

结果包括:

_________________________________________________________________

使用以下命令列出文件名中第四个字符为1到3的文件:

       $ ls inv[1-3]jig.c

结果包括:

_________________________________________________________________

使用以下命令列出文件名中在inv和jig中间夹着任何长度字符串的文件:

       $ ls inv*jig.c

结果包括:

_________________________________________________________________

使用以下命令将列出文件名中至少包含一个数字并且扩展名为“.c”或“.o”的文件:

       $ ls *[0-9]*.[co]

结果包括:

_________________________________________________________________

Linux中目录的概念与DOS或Windows差不多,只是在DOS或Windows中目录用“\”号表示,而在Linux则用“/”号表示。

与DOS或Windows一样,Linux的目录也可以采用绝对与相对路径表示。在Linux操作系统中,不管是文本模式还是图形模式,其所有的文件布局都是树型目录方式。

为返回工作目录,无论现在处于何级目录位置,只要键入“cd”命令即可返回登录时的工作目录。键入pwd,可查到当前工作目录的完全路径。记录下当前的工作目录:

_________________________________________________________________

还可以通过一个“~”字符来引用自己的主目录,例如:

       /home/CAI $ ls ~class/

等价于

       /home/CAI $ ls /home/CAI/class/

    5. Linux的文件系统

1) 本次实验使用的Linux系统的版本是:

_________________________________________________________________

2) 在Linux文件系统根目录下有哪些子目录:

_________________________________________________________________

_____________________________________________________________________

_____________________________________________________________________

(例如:bin、dev、etc、home、install、lib、mnt、proc、root、tmp、user、var,注意区分不同版本目录的不同) 。

3) 用“ls  –f  /bin”命令列出 /bin系统目录中的文件个数和主要文件:

___________________________________________________________     ______

_____________________________________________________________________

_____________________________________________________________________

_____________________________________________________________________

_____________________________________________________________________

_____________________________________________________________________

_____________________________________________________________________

2、Linux文件信息命令和基本文件管理

1. 文件信息命令

步骤1:开机,登录进入GNOME。

在GNOME登录框中填写指导老师分配的用户名和口令并登录。

步骤2:访问命令行。

单击红帽子,在“GNOME帮助”菜单中单击“系统工具”-“终端”命令,打开终端窗口。

步骤3:使用控制字符执行特殊功能。

控制字符用来执行特殊的作业,如中止和启动屏幕输出。

大多数PC键盘有两个控制键。它们通常标记为Ctr1,可以在键盘的左右下角找到。为了输入一个控制字符序列,可按住Ctrl键不放,然后按下键盘上相应的字符。

Ctrl + C:中断当前活动。当你在csh中键入一个不可识别的命令行 (例如,$ls “) ,收到第2个提示符的时候,Ctrl + C也可以用于恢复shell提示符。

Ctrl + Z:终止当前活动。显示ls命令的手册页面 (man ls) ,然后使用Ctrl -z中止输出。

当你接下Ctrl + Z的时候,发生了什么事情?

    _________________________________________________________________

Ctrl + D:表示文件的末尾或者退出。 Ctrl + D用于退出一些Linux工具程序 (bc、write等) ,退出一个终端窗口,注销一个终端会话或者命令行登录会话。作为一个一般的规则,当您出现“死机”时,或者如果Ctrl + C不起作用,可试试Ctrl + D。例如:

1) 在shell提示符下键入bc,启动基本的计算器工具程序。

2) 把两个数字相乘 (键入:458*594,然后按回车键) 。

3) 按Ctrl + D退出计算器。

当使用计算器的时候,你的提示符是什么?

    _________________________________________________________________

Ctrl + U :擦除整个命令行。Ctrl + U最常用在:

· 一个擦除决定不执行的命令行的快捷方式。

· 如果登录到一个远程系统,退格键不起作用。

· 它可以确保在登录的时候,从一个“空”的用户帐号和口令输入开始。

· 因为在口令输入的时候看不见它们,当知道自己键入了错误字符的时候,使用Ctrl + U擦除密码,重新开始输入。

如果输入一个命令,如ls –R/,有时候,会在按下回车键之前想擦除命令行。输入一个命令,在接下回车键执行命令之前按下Ctrl + U。结果是什么?

    _________________________________________________________________

_____________________________________________________________________

步骤4:使用file命令确定文件类型。

在Linux系统中可以找到许多类型的文件。文件类型可以通过使用file命令来确定。当一个用户试图打开或阅读一个文件的时候,这个信息很重要。确定文件类型可以帮助一个用户决定使用哪个程序或命令来打开这个文件。这个命令的输出最常见的是如下几种:文本文件、可执行文件或数据文件。

1) 文本文件:包括ASCII或英语文本、命令文本和可执行的shell脚本。这种类型的文件可以使用cat或more命令读取,可以使用vi或其他文本编辑器编辑。

单击红帽子,在“GNOME帮助”菜单中单击“辅助设施”-“Text Editor”命令,在文本编辑中键入适当内容并保存为test文件。

使用file命令来确定test文件的文件类型。它是哪种类型的文件?

    _________________________________________________________________

2) 可执行 (或二进制) 文件:包括32位的可执行文件和可扩展链接格式(ELF) 编码文件,和其他动态链接的可执行文件。这种文件类型表示这个文件是一个命令或程序。

单击红帽子,在“GNOME帮助”菜单中单击“办公”-“OpenOffice.org Writer”命令,建立一个文档如ww.sxw。

使用file命令确定你所建立的文件类型。它是哪种类型的文件?(注意文件名部分必须包括扩展名,如file ww.sxw 。)

    _________________________________________________________________

3) 数据文件:数据文件是由系统中运行的应用创建的。在某些情况下,文件的类型是会说明的。例如,FrameMaker (桌面印刷软件) 文档。

使用file命令确定dir1/coffees子目录中beans文件的文件类型。它是什么文件类型的?

    _________________________________________________________________

步骤5:使用strings命令。

strings命令可以用于打印可执行文件或者二进制文件中的可读字符。

一些有编程背景的人,可以解释strings产生的输出。这个命令在这里只是作为一个展示可执行文件中可打印字符的方法来介绍。strings命令必须用于读取可执行文件,如 /usr/bin/cat。在大多数情况下,strings命令也可以给出命令的使用语法。

使用strings命令查看 /usr/bin/cal文件的可读字符。列出strings命令中的一些输出。

    _________________________________________________________________

_____________________________________________________________________

_____________________________________________________________________

步骤6:使用cat命令显示文件的内容。

cat命令在屏幕上显示一个文本文件的内容。它常用于显示如脚本文件 (类似批处理文件) 这样的短文本文件。如果文件超过一屏的话,必须使用一个屏幕可以滚动的窗口,如GNOME环境中的终端窗口。

键入 ls /dev > dev1

使用cat命令显示主目录中dev1文件的内容。文本的显示出现了什么情况?

    _________________________________________________________________

步骤7:使用more命令显示文件的内容。

more命令是一个用于显示文本文件首选的方法,因为它会自动的一次显示一屏文件内容。如果文件的信息比一屏更长,屏幕的底部显示如下的信息:--More-- (n%) (文件的n%已经显示) 。按下回车键,继续一次显示一行信息。空格键将继续一次显示一屏内容。

使用more命令显示主目录中dev1文件的内容。文本的显示出现了什么情况?

    _________________________________________________________________

步骤8:使用head命令显示文件的一部分。

head命令用于显示一个或多个文本文件的前n行。在默认情况下,如果没有给出 -n选项,将显示前10行。当您只想查看文件的开始的几行,而不管文件的大小的时候,head命令是很有用的。

1) 单独使用head命令,显示主目录中dev1文件的开始部分。显示了多少行?

    _________________________________________________________________

2) 使用带 -n选项的head命令,显示主目录中dante文件的前20行。您输入什么命令?

    _________________________________________________________________

步骤9:使用tail命令显示文件的一部分。

使用tail命令,显示文件的最后几行。在默认情况下,如果没有指定 -n选项,将显示最后10行。当检查大型日志文件最近输入内容的时候,tail命令是很有用的。备份工具程序常把备份哪个文件和什么时候做的备份,写到日志文件中去。一个备份日志文件中最后的输入通常是备份文件的总数和备份是否成功完成的信息。-n选项显示了文件的最后n行。

单独使用tail命令,显示主目录中dante文件的末端。显示了多少行?

    _________________________________________________________________

步骤10:通过使用wc命令,确定行数、单词数和字符数。

wc (单词计数) 命令可以用于显示文本文件的行数、单词数、字节数或者字符数。当确定文件特征或者当比较两个文件的时候,这个命令是很有用的。使用不带选项的wc将给出文件的行数、字节数。使用带一个选项的wc,可以确定想查看的哪一项内容。

使用wc命令确定主目录中dev1文件的行数、单词数和字符数。有多少行、多少个单词和多少个字符?

    _________________________________________________________________

步骤11:使用wc计算目录条目的数目。

使用wc和ls命令确定主目录中条目 (文件和目录) 的数目。为此,必须把ls命令的输出导入到wc命令中。

更多符号是竖线,和后斜线 (\) 在同一个键上。在命令行提示行下,输入命令ls l wc -w。有多少个文件和目录名 (单词) ?

    _________________________________________________________________

步骤12:使用diff命令确定文件之间的不同之处。

diff (不同) 命令用于比较2个文本文件,找出在它们之间的不同之处。wc命令可以比较文件,因为它计算行数、单词数和字符数。有可能2个文件有相同的行数、单词数和字符数,但是字符和单词不同。diff命令可以从实际上找出文件之间的不同。

这个命令的输出把2个文本文件之间的不同一行一行的显示出来。diff命令有2个选项:-i 和 -c。-i选项忽略字母的大小写,例如A和a相等。-c选项执行细致的比较。

单击红帽子,在“GNOME帮助”菜单中单击“辅助设施”-“Text Editor”命令,创建两个文件fruit1和fruit2,并键入适当内容。

使用diff命令执行细节比较,确定fruit1文件和fruit2文件之间的区别。

在fruit1文件和在fruit2文件中,哪几行是不同的?

    _________________________________________________________________

_____________________________________________________________________

_____________________________________________________________________

1) cat命令:

· 对fruit1文件使用cat命令。

· 对fruit2文件使用cat命令。

· 键入命令行cat fruit1 fruit2 > filex。

· 对filex文件使用cat命令。上面的命令行做了什么工作?

    _________________________________________________________________

2) 可以使用哪2个命令来确定2个文件是否相同?

    _________________________________________________________________

步骤13:关闭终端窗口,注销。

    2. 基本的命令行文件管理

步骤14:回顾Linux的文件和目录命名规则。

在本实验中,我们将创建文件和目录,因此,在开始之前,先来回顾一下Linux文件和目录的命名规则和指导方针。

1) 最大长度:组成文件和目录名最大长度为255个数字字母字符。一般来说,应该尽可能的保持文件名短但是仍然有意义。

2) 非数字字母字符:一些非数字字母字符或者元字符是可用的:下划线 (_) 、连字符号 (-) 和句点 (.) 。这些元字符可以在文件或目录名中使用多次(Feb.Reports.Sales是一个有效的文件或目录名) 。尽管shell允许把星号 (*) 、问号(?) 和发音符号 (~) 、方话号 ([ ]) 、&、管道 [ | ] 、引号 (“”) 和美元符号 ($) 在文件名中使用,但这不是推荐的,因为这些字符对于shell有特殊的意义。分号 (;) 、小于号 (<) 和大于号 (>) 是不允许作为文件名的。

3) 文件名扩展:文件名可以包含一个或多个扩展名。扩展名常被一个应用追加到文件的末端。扩展名通常是1个到3个字符,追加到文件名的末端,之前有一个句点 (.) 。当命名文件的时候,您可以选择使用这个规则。

4) 目录名的扩展名:目录名一般不包含扩展名,但是也没有规则反对这一点。

5) 大小写敏感:Linux文件和目录名是大小写敏感的。Project1和projectl不是同一个文件。在一个目录中,不能够有两个文件有着同样的名字。一般规则都是使用小写字母。

检查表7-1中的文件名,指出它们是否是有效或者推荐的Linux文件或目录名,为什么是或为什么不是。

表7-1  实验记录

文件名

是否为Linux文件或目录名

为什么是或为什么不是

12345abcde678

Hobbies: 2

Adcd-123

Sales*repts*2001

D.projects.bj.2001

Projects>1.bj-2001

步骤15:使用touch命令创建文件。

每次创建一个新的字处理文档或者电子数据表,就是正在创建一个新文件,应该符合之前提到的文件命名规则。也必须拥有创建文件的目录的足够权限。

使用touch命令,可以同时创建一个或多个文件。一些应用要求在写文件之前,文件必须存在。touch命令对于快速创建需要处理的文件很有用。也可以使用touch命令更新文件被访问的时间和日期,使文件可以再次被备份。当创建文件或目录的时候,可以指定绝对和相对的路径名。

命令格式:

touch filename (s)

1) 在主目录中使用touch命令创建一个名为newfile的文件,应该使用什么命令?

    _________________________________________________________________

2) 使用touch命令在这个目录中创建另一个叫做filenew的新文件,应该使用什么命令?

    _________________________________________________________________

3) 输入命令显示practice目录中的文件的长列表。创建的文件列出来了吗?

    _________________________________________________________________

4) 谁是文件的所有者?

    _________________________________________________________________

5) 和文件关连的组是什么?

    _________________________________________________________________

6) 创建的日期和时间是什么?

    _________________________________________________________________

7) 文件的大小是多少?

    _________________________________________________________________

8) 使用file命令确定newfile的文件类型。它是哪一类的文件?

    _________________________________________________________________

9) 使用touch命令同时创建3个文件:new1、new2和new3,应该使用什么命令?

    _________________________________________________________________

10) 输入命令显示practice目录中文件的长列表。创建的3个新文件列出来了吗?

    _________________________________________________________________

步骤16:使用mkdir命令创建新目录。

mkdir (创建目录) 命令用于创建目录或文件夹。目录可以包含其他目录,称为子目录,它们可以包含文件。

    目录可以使用或者绝对路径名或者相对路径名创建。可以在同一行中指定多个目录名,创建多个新目录。必须有创建目录的足够权限。

mkdir directory_name (s)

1) 从主目录中,使用相对路径名改变到practice目录中。使用什么命令?

    _________________________________________________________________

2) 使用mkdir命令,在这个目录中创建一个叫做newdir的子目录。使用什么命令?

    _________________________________________________________________

3) 输入命令,显示practice目录中文件和目录的长列表。创建的目录列出来了吗?

    _________________________________________________________________

4) 目录的所有者是?

    _________________________________________________________________

5) 文件的大小是多少?

    _________________________________________________________________

6) 使用file命令确定newdir文件的类型。它是哪一类的文件?

    _________________________________________________________________

7) 如果名字中没有字符dir,采取别的什么方法来识别出它是一个目录?

    _________________________________________________________________

8) mkdir命令创建3个目录,目录名分别为high、medium和low,应该使用什么命令?

    _________________________________________________________________

9) 用ls命令检查创建是否成功?

步骤17:使用rm命令删除文件。

rm目录可以删除单个文件或多个文件。可以通过在rm命令之后指定文件的名字,或者使用星号 (*) 和问号 (?) 元字符,同时删除几个文件。在Linux系统中删除的文件是永远被删除了,除非使用图形界面删除文件,它们才能够被恢复。rm命令可以带 –i (交互) 选项使用,它在删除文件之前会提示用户。使用rm -i命令作为防范,避免误删文件:

rm [-i] filename (s)

1) 使用rm命令删除早先在practice目录中创建的newfile文件,应该使用什么命令?

    _________________________________________________________________

2) 输入命令显示practice目录中文件的长列表。创建的文件还在吗?

    _________________________________________________________________

3) 使用带 -i选项的rm命令,删除早先在practice目录中创建的filenew文件。交互式选项起到什么作用?

    _________________________________________________________________

4) 删除早先创建的三个名为new1、new2和new3的文件。使用问号 (?) 通配符使用一个命令删除所有三个文件。使用什么命令?

    _________________________________________________________________

5) 输入命令,显示practice目录中文件的长列表。三个文件还在吗?

    _________________________________________________________________

6) 还有其他的什么方法来删除new1、new2和new3文件?

    _________________________________________________________________

步骤18:使用rm -r命令删除目录。

rm -r目录用于删除目录。它将删除从目标目录开始的目录,包括所有的子目录和文件。当rm命令带 -r信息使用的时候,它可以删除单个目录 (空或不空) 或目录树的整节。rm命令可以带 -i选项使用,它在删除目录之前会提醒用户:

rm –r [i] directory_name (s)

1) 删除早先创建的newdir子目录,使用什么命令?

    _________________________________________________________________

2) 输入命令显示practice目录中文件的长列表,创建的子目录还在吗?

    _________________________________________________________________

3) 改变到早先创建的mediurn子目录中,输入什么命令?

    _________________________________________________________________

4) 删除早先创建的low子目录,使用什么命令?

    _________________________________________________________________

5) 用相对路径名和快捷方式,改变回到practice子目录中,应使用什么命令?

    _________________________________________________________________

6) 使用一个命令删除high和medium子目录,应使用什么命令?

    ____________________________________________________________________

步骤19:练习所学习到的内容。

通过在practice目录中创建一个三级的目录树,练习使用touch、mkdir和rm命令。试着使用有意义的目录名。记住可以使用一个命令创建整个目录结构。在每个目录中创建多个文件。记住可以使用一个命令创建多个文件。

结束的时候,请删除实验时创建的文件和目录。

步骤20:关闭终端窗口,注销。

3、Linux文件权限

  1. 确定文件系统权限及在命令行中修改权限

步骤1:开机,登录进入GNOME。

在GNOME登录框中填写指导老师分配的用户名和口令并登录。

步骤2:访问命令行。

单击红帽子,在“GNOME帮助”菜单中单击“系统工具”-“终端”命令,打开终端窗口。

步骤3:显示权限。

权限控制着谁能够对文件系统中的文件和目录做什么。目录和文件权限可以使用带 –l (长列表) 选项的ls (列表) 命令来确定。ls -l命令显示目录内容的长列表。如果同时给出 -a选项,则所有文件,包括隐藏文件和目录 (那些以圆点打头的) 都被显示出来。

表8-2提供了检查使用ls -l目录列出的信息。

表8-2

文件类型

第一个位置的短横线表示一个普通文件。一个d表示目录

权限

3组权限:用户,属组,其他

链接

链接到其他文件和目录

所有者

创建文件或目录的用户的用户 (登录ID) ,除非指派了所有权

属组

所有者属于的属组名,由系统管理员建立

大小

文件按字节计算的大小

修改日期/时间

文件创建或最后修改的月、日、年 (如果不是当年) 和时间

文件名

文件或目录名

    注意当使用权限工作的时候,文件类型、权限、所有者、属组和文件/目录名是列表中最重要的信息片断。

1) ls 的第一个位置______________对文件或目录列表______________表示文件类型。使用ls –l命令列出主文件夹中的文件。/bin/cal的文件类型是什么 (文件或目录) ?如何知道的?

    _________________________________________________________________

2) 接下来的ls中的9个位置______________表示文件的权限。所有文件或目录可能的权限是:(小写) r、w、x或短横线 (-) 。cal的权限是什么?

    _________________________________________________________________

步骤4:解释权限。

请参阅表8-3,回答下面的问题。注意到权限的解释对于文件和目录是不同的。

1) 文件的r权限的意义是什么?

    _________________________________________________________________

_____________________________________________________________________

2) 目录的r权限的意义是什么?

    _________________________________________________________________

_____________________________________________________________________

表8-3  普通文件目录的权限符号

权限

符号

普通文件

目录

r

文件可以被显示或者拷贝 (拷贝的文件属于新的所有者) 。只有读权限不能够删除或移动文件

可以使用ls命令列出内容。必须也有使用ls命令选项的执行权限

w

文件可以被修改、移动和删除 (只有当目录给出写权限的时候)

文件可以被添加或删除。目录必须也有执行权限

执行

x

文件可以被执行 (shell脚本或者可执行文件)

控制对目录的访问。用户可以cd到目录中,使用读访问列出其中的内容。文件可以使用写访问被移动或者拷贝到目录中

无权限

-

短横线表示权限被拒绝

短横线表示权限被拒绝

3) 文件的X权限的意义是什么?

    _________________________________________________________________

4) 文件的w权限的意义是什么?

    _________________________________________________________________

5) 目录的w权限的意义是什么?

    _________________________________________________________________

6) 权限位置的短横线 (-) 的意义是什么?

    _________________________________________________________________

步骤5:确定文件的用户权限。

九个权限被分成三个权限一组。每组的三个权限总是按照r (读) w (写) 和x (执行) 的顺序排列。如果权限不允许,短横线 (-) 将在它的位置。第1组三个权限是用户的权限组。这些权限决定其所有者能够做什么。

在主目录中创建一文件dante。单击红帽子,在“GNOME帮助”菜单中单击“辅助设施”-“Text Editor”命令,在文本编辑中键入适当内容并保存为dante。

1) 谁是dante文件的所有者?

    _________________________________________________________________

2) 用户权限的头2个字符是什么?

    _________________________________________________________________

3) 在用户的权限组中,第3个位置是什么?

    _________________________________________________________________

4) 列出根据所给的文件权限,用户 (所有者) 能够做的4件事情。

    _________________________________________________________________

_____________________________________________________________________

_____________________________________________________________________

_____________________________________________________________________

步骤6:确定文件的属组权限。

系统管理员给每一个用户分配了一个主属组。这个文件所有者所在的属组是一个当该文件创建时,随所有者一起分配的成员。第2组的3个权限决定了主属组的成员能够做什么。

1) dante文件的所有者是什么主属组的成员?

    _________________________________________________________________

2) 属组权限的第一个字符是什么?

    _________________________________________________________________

3) 这允许属组的其他成员对文件进行什么操作?

    _________________________________________________________________

4) 为什么在接下来的第二和第三个位置不是w和x,而是短横线?

    _________________________________________________________________

步骤7:确定文件的其他 (公共) 权限。

最后一组字符,叫做其他权限,是其他每一个人都有的权限。其他指既不是文件所有者也不是文件所有者所在属组的成员,但是有权访问系统的所有人。

不是所有者和属组的其他人对dante文件有什么权限?

    _________________________________________________________________

步骤8:确定可执行文件的文件权限。

可执行文件,例如Linux工具程序和脚本文件,对于想执行命令或者脚本的所有人要求 (执行) 权限。

1) 从主目录中显示在 /usr/bin目录中的bc文件的长目录列表。使用什么命令?

    _________________________________________________________________

2) 文件的权限是什么?

    _________________________________________________________________

3) 用户权限是什么?

    _________________________________________________________________

4) 属组权限是什么?

    _________________________________________________________________

5) 其他权限是什么?

    _________________________________________________________________

6) 为什么组属用户和其他用户类别没有w (写) 权限?

    _________________________________________________________________

步骤9:使用默认权限创建一个新文件。

使用默认权限创建新文件。使用touch命令在主目录中创建一个新文件。

1) 在主目录中创建一个叫做newfileperms的新文件。使用什么命令和路径名?

    _________________________________________________________________

2) 查看newfileperms的权限。使用什么命令和路径名?

    _________________________________________________________________

3) 分配给这个文件的默认权限是什么?

    _________________________________________________________________

4) 谁是所有者?

    _________________________________________________________________

5) 谁是主属组?

    _________________________________________________________________

6) 主属组的成员能够重新命名这个文件吗?

    _________________________________________________________________

步骤10:使用默认权限创建一个新目录。

也可以使用不同的默认权限创建新目录。使用mkdir命令在主目录中创建一个新目录。

1) 在主目录的practice目录中创建一个叫做newdirperms的新目录。使用什么命令和路径名?

    _________________________________________________________________

2) 列出主目录中的内容,查看newdirperms的权限。使用什么命令和路径名?(注:先退回到主目录的上级目录中。)

    _________________________________________________________________

3) 分配给这个目录的默认权限是什么?

    _________________________________________________________________

4) 谁是所有者?

    _________________________________________________________________

5) 谁是主属组?

    _________________________________________________________________

6) 一个主属组的成员能够在这个目录中添加文件吗?

    _________________________________________________________________

步骤11:回顾chmod命令模式。

chmod (修改模式) 命令被文件所有者 (或超级用户) 用来修改文件权限。chmod命令的2种操作模式是符号 (或相对) 和八进制 (或绝对) 。chmod命令通用的格式是:

  chmod mode filename

模式部分会根据是使用符号模式还是使用八进制模式而做修改。

· 符号模式:使用字母与符号的组合,为不同类别的用户添加或删除权限。符号模式也叫做相对模式。

· 八进制模式:使用数字表示文件权限。八进制模式也叫做绝对或者数字模式。

1) 哪种chmod模式使用数字表示文件权限?

    _________________________________________________________________

2) 哪种chmod模式使用字母 (或符号) 表示权限?

    _________________________________________________________________

步骤12:使用符号模式修改文件权限。

当 使用符号模式设定权限的时候,尽管会同时给所有类别的用户同样的权限,一般只对一种类别的用户工作。这个模式叫做相对模式,因为正在相对已经存在的权限进 行分配或删除权限。可以给一个特定类别的用户添加或删除一个或多个权限,或者把权限都取走。符号模式的命令格式使用字母和符号。命令格式的模式部分由3个部分组成:

· 谁:要处理的用户的类别:u = 用户,g = 属组, o = 其他,还有a = 所有。

· 操作:操作或者想做的事情:设定 (=) ,删除 (-) ,给予 (+) 。

· 权限:分配的权限:r = 读,w = 写,还有x = 执行。

下面的例子删除 (-) 了文件dante中其他 (o) 类别用户的读 (r) 权限。 注意:在o 短横线 (-) 和r之间没有空格。

  chmod o-r dante

下面的例子给文件dante添加 (+) 了属组 (g) 和其他 (o) 类别用户的写 (w) 权限:

  chmod go+w dante

1) 在主目录中使用相对路径名创建一个叫做chmoddir的新目录。使用什么命令创建目录?

    _________________________________________________________________

2) 改变到chmoddir目录中,创建一个叫做symfile的新文件。使用什么命令创建文件?

    _________________________________________________________________

3) 使用ls -l命令来确定symfle的权限。这些是文件的默认权限。用户、属组和其他的权限是什么?

    _________________________________________________________________

4) 决定不想让其他用户 (除了自己和属组成员之外) 能够查看symfle的内容和拷贝symfle。使用chmod命令,在符号模式下,删除其他用户对于文件symfle的读权限。使用什么命令?

    _________________________________________________________________

5) 再次列出文件的权限。其他类别用户的权限现在是什么?

    _________________________________________________________________

6) 如果想只使用一个命令删除属组和其他类别的读权限,使用什么命令?

    _________________________________________________________________

步骤13:使用符号模式修改目录权限。

1) 改变回到主目录,使用什么命令?

    _________________________________________________________________

2) 从主目录中列出早先创建的新的chmoddir目录的权限。这些是目录的默认权限。用户、属组和其他的权限是什么?

    _________________________________________________________________

3) 除了自己或者属组成员以外的其他用户能够从chmoddir目录中拷贝文件吗?

    _________________________________________________________________

为什么能或者为什么不能?

    _________________________________________________________________

4) 不想让其他用户从chmoddir目录中拷贝文件。改变到主目录中,使用chmod命令,在符号模式下,删除其他类别用户对于目录chmoddir的读和执行权限。使用什么命令?

    _________________________________________________________________

5) 再次列出目录的权限。其他类别用户的权限是什么?

    _________________________________________________________________

6) 主属组成员能够在你的chmoddir目录中创建或者拷贝文件吗?为什么能或者为什么不能?

    _________________________________________________________________

_____________________________________________________________________

7) 改变到主目录,使用chmod命令,在符号模式下,给主属组去除对目录chmoddir的读权限。使用什么命令?

    _________________________________________________________________

8) 通过使用符号模式把权限改回默认的权限。使用什么命令?(提示:属组和权限可以使用一个命令组合,或者可以使用2个分离的命令。)

    _________________________________________________________________

步骤14:确定八进制权限。

    八进制模式为同时修改所有类别用户的权限提供了一个快捷的数字方式,而且仍然允许每组权限可以是不同的。有3组可能的权限 (r、w和x) ,对应于每种用户类别 (用户、属组或其他) 。每组权限可以根据允许的权限使用数字 (0到7) 来分配。

r (读) 权限指派为数字4,w (写) 权限指派为数字2,x (执行) 权限指派为数字1。通过添加数字,我们得到一个总的对应于用户类别 (用户、属组或其他) 的3个权限。例如,如果用户 (所有者) 对于文件的权限是rwx,我们把4 (读) 加上2 (写)加上1 (执行) 得到7。如果属组有rw权限,它们得到4+2+0 (没有执行权限) 的总数6。如果其他只有r权限,它们得到4+0+0 (没有写和执行权限) 的总数4。这个文件或目录的octal_mode是764。

1) 通过把字符权限转换成等效的八进制,填入表8-4。先转换每组权限 (用户、属组或其他) ,然后在八进制模式权限下输入octal_mode (3个数字) 。

表8-4  实验记录

用户权限

八进制数

属组权限

八进制数

其他权限

八进制数

八进制

模式权限

r w x

r w -

r w -

r w -

r - -

r - -

r - -

r - -

r - -

r w x

r – x

r – x

步骤15:使用八进制模式修改文件权限。

使用八进制模式,没有必要指定用户的类别,因为每个数字的位置表示了三种用户类别中的一种。Octal_mode由三个数字组成,每个都是一种用户类别 (用户、属组或其他) 的总和。八位数值组合在一起标识了用于chmod命令的octal_mode。

  chmod octal_mode filename

1) 改变到chmoddir目录中,创建一个叫做octfile的新文件。使用什么命令创建文件?

    _________________________________________________________________

2) 使用ls -l命令来确定octfile的权限。这些是文件的默认权限。什么是用户、属组和其他的数字权限?

    _________________________________________________________________

3) 与这个文件的用户、属组和其他权限等同的八进制模式是什么?

    _________________________________________________________________

4) 决定不想让其他用户能够查看或者拷贝octfile文件的内容。使用chmod命令,在八进制模式下,删除其他用户对于octfile的r (读) 权限。使用什么命令?

    _________________________________________________________________

5) 再次列出文件的权限。其他用户类别现在的权限是什么?

    _________________________________________________________________

6) 如果想只使用一个命令,删除属组和其他类别的所有权限,使用什么命令?

    _________________________________________________________________

步骤16:使用八进制模式修改目录权限。

下面的格式用于修改目录的权限。-R (递归) 选项修改指定目录的权限,包括其中的所有子目录和文件。

  chmod [-R] octal_mode directoryname

1) 改变到主目录。使用什么命令?

    _________________________________________________________________

2) 从主目录中列出chmoddir目录的权限。这些是目录的默认权限。对于用户、属组和其他,数字极限是什么?

    _________________________________________________________________

3) 什么是和用户、属组和其他对于这个目录等同的八进制模式?

    _________________________________________________________________

4) 使用chmod命令,在八进制模式下,删除其他类别用户对于目录chmoddir的读和写权限。使用什么命令?(记住:在八进制模式下,必须总是指定所有的3组权限,即使它们可能没有被修改。)

    _________________________________________________________________

5) 再次列出目录的权限。其他用户类别的权限现在是什么?

    _________________________________________________________________

用户和属组的权限保持不变吗?

    _________________________________________________________________

6) 全属组 (核心组) 成员能够在chmoddir目录中创建新文件或者拷贝文件吗?为什么能或者为什么不能?

    _________________________________________________________________

_____________________________________________________________________

7) 决定让属组成员能够从你的目录中拷贝文件。改变到主目录,使用chmod命令,在八进制模式下,给主属组 (核心组) 添加对目录chmoddir的写权限。用户有权限rwx,属组应该有权限rw,其他应该对目录没有权限。使用什么命令?

    _________________________________________________________________

8) 使用八进制模式把权限改回默认权限 (rwxr-xr-x) 。

    _________________________________________________________________

步骤17:创建一个脚本文件,使它能够执行。

在本步骤中,将使用vi编辑器创建一个简单的文本脚本文件。为了能够运行脚本文件,然后需要使它可以执行。脚本文件在帮助自动重复作业的时候非常有用。

1) 改变到chmoddir目录,使用vedit启动vi编辑器。当启动编辑器的时候,指定或者打开一个新文件叫做myscript。按下i进入插入输入模式,以小写文本键入下面的命令。在每行后按回车键。

  echo  “hello!”

2) 按下ESC键,返回命令模式,然后输入一个冒号,进入末行模式。按下wq来写入 (保存) 文件,然后退出vi。

    _________________________________________________________________

3) 列出文件,确定它的权限。它们是什么?

    _________________________________________________________________

4) 键入 ./myscript,就像它是一个命令,然后按下回车键。命令的响应是什么?

    _________________________________________________________________

为什么它不执行?

    _________________________________________________________________

5) 修改myscript的权限,这样用户权限包括x (执行) ,作为所有这可以执行或运行文件。可以使用符号模式或者八进制模式。使用什么命令修改权限?

    _________________________________________________________________

6) 列出文件,检查修改的权限。用户 (所有者) 现在的权限是什么?

    _________________________________________________________________

7) 再次把myscript作为一个命令键入,然后按下回车键。命令的响应是什么?

    _________________________________________________________________

步骤18:删除在本实验中创建的文件和目录。

删除在本实验过程中在你的主目录中创建的所有文件和目录。

步骤19:关闭终端窗口,注销。

    2. 使用文件管理器修改权限

步骤1:登录进入GNOME。

步骤2:访问文件管理器。

文件管理器可以通过双击桌面上的起始目录图标,打开一个主文件夹中的文件夹视图。从那个文件夹可以改变到其他文件夹中,沿着层次结构向上或者向下,查看每个文件夹的内容。路径总是显示在文件管理器窗口的“位置”区域。

双击桌面上的起始目录图标,当前文件夹的路径是什么?

    _________________________________________________________________

步骤3:使用文件管理器查看和修改文件权限。

可以从文件管理器窗口中选择文件或文件夹,单击鼠标右键,单击Properties命令,在“属性”对话框中查看和修改它们的属性。单击“权限”按钮,可以查看和修改权限。为了给所有者 (用户) 、属组和其他修改权限,可通过单击确认框选择想要的权限。

1) 右键单击dante文件,单击Properties命令,然后单击“权限”按钮。dante文件的权限是什么?

    _________________________________________________________________

2) 在主目录中,使用File菜单创建一个叫做fmfile的新文件。右键单击这个文件,单击Properties命令,在“属性”对话框中单击“权限”按钮。这个文件的权限是什么?

    _________________________________________________________________

3) 在设定其他用户读访问的确认框上单击,取消选择 (清除确认标记) 。除了你自己或者属组员之外的用户现在还能查看这个文件的内容吗?

    _________________________________________________________________

关闭fmfile的属性窗口。

4) 使用文件管理器,浏览 /usr/bin文件夹的文件系统结构。定位cal命令文件。文件图标上的符号是什么?

    _________________________________________________________________

5) 右键单击cal文件,单击Properties命令,在“属性”对话框中单击“权限”按钮。cal文件的权限是什么?

    _________________________________________________________________

6) 现在已经看到这个文件的权限,你认为那个图标表示什么意思?

    _________________________________________________________________

7) 单击设定其他用户读访问的确认框,取消选择 (清除确认标记) 。能够这样做吗?

    _________________________________________________________________

8) 关闭cal文件的属性窗口。

步骤4:使用文件管理器检查和修改文件夹权限。

1) 使用文件管理器,浏览主文件夹,创建practice文件夹。右键单击practice文件夹,单击Properties命令,在“属性”对话框中单击“权限”按钮。practice文件夹的权限是什么?

    _________________________________________________________________

2) 改变到practice文件夹,创建一个叫做fmfolder的新文件夹。右键单击这个文件夹,单击Properties命令,在“属性”对话框中单击“权限”按钮。这个文件夹的权限是什么?

    _________________________________________________________________

3) 单击设定其他用户读访问和执行访问的确认框,取消选择 (清除确认标记) 。现在除了你自己或者你的属组员之外的其他用户还能够查看这个文件夹的内容或者从其中拷贝文件吗?

    _________________________________________________________________

4) 单击设定你的属组 (核心组) 写访问的确认框,进行选择 (添加确认标记) 。你的属组员能够修改fmfolder中的文件了吗?

    _________________________________________________________________

5) 关闭fmfolder的属性窗口。

6) 使用文件管理器,浏览 /root文件夹。这个文件夹图标上的符号是什么?表示什么意思?

    _________________________________________________________________

_____________________________________________________________________

_____________________________________________________________________

步骤5:删除所有在本实验过程中在你的主目录中创建的文件和目录。

步骤6:关闭GNOME文件管理器,注销并退出

二、实习总结

Unit 3  Linux vi的使用

【实习要求】

掌握vi编辑器的基本使用

    包括:启动、退出、增、删、改、复制、粘贴、查找、替换等基本操作

【实习内容】

Linux vi编辑器

【实习指导】

vi是所有Linux发行版中均提供的一个标准的全屏幕编辑器,它具有强大的文本编辑功能。下面仅对其最基本功能进行介绍。

3.1 vi的启动与退出

1vi的启动

在shell提示符下,启动vi编辑器的命令的基本格式如下:

格式:vi  [filename]

功能:启动vi编辑器,且同时打开由filename指定的文件。若filename指定的文件不存在,则vi新建该文件;若命令中缺省filename,则vi新建一文件,在退出 vi前要求用户给出该新文件的命名。

例如,在shell提示符下,键入如下命令“vi  /home/user/test1”,屏幕显示如图3-1所示,图中“~”表示该行为空行,还未使用。

图3-1

vi提供了三种编辑模式:命令模式(command mode)、输入模式(input mode)和底行命令模式(last line mode)。

命令模式让用户执行丰富的编辑命令;输入模式让用户输入正文内容;底行命令模式则让用户执行打开文件、保存文件、搜索字符串及退出vi等操作命令。进入vi时的默认模式是命令模式。

2、不同模式间的转换

(1)命令模式与输入模式间的切换

在命令模式下,按<a>或<i>键,便切换到输入模式,如图示3-2所示,图中屏幕底部(即最后一行)显示输入模式的当前状态。

图3-2

若要从输入模式返回到命令模式,则按键<Esc>。此时输入模式的底行输入状态的提示消失。

(2)命令模式与底行命令模式间的切换

在命令模式下,按键<:>,便切换到了底行命令模式。当进入底行命令时,在屏幕的底部会有提示符“:”出现,如图示3-3所示。

图3-3

若要从底行命令模式返回到命令模式,则按键<Esc>即可。此时底行的提示符“:”消失。

3vi的退出

在底行命令模式的提示符“:”下,键入命令 “q!”或“wq”,便退出vi编辑器,返回到shell提示符下。命令“q!”和“wq”的作用如下:

q!:不保存文件的编辑,退出vi,。

wq:保存文件的编辑后,退出vi,

3.2 光标移动

在vi中,除了用方向键(↑、↓、←、→)、<Home>键和<End>键,进行上下左右移动、前翻页和后翻页外,还可以在底行命令模式下键入命令移动光标。

1、光标移至指定行命令

格式:[n]G

功能:将光标移至由n(n代表行号)指定的行的行首,当命令缺省n时,则将光标移至文件最末一行的行首。

例如,若要将光标移到文件首,则键入命令“1G”。

例如,若要将光标移到文件尾行,则键入命令“G”。

例如,若要将光标移到文件的第三行,则键入命令“3G”。

2、光标在段落间移动的命令

命令:{

功能:将光标移到上一段的开头。

命令:}

功能:将光标移到下一段的开头。

3.3 编辑操作

1、输入

在命令模式下,按键<a>或<i>或<o>,切换到输入模式后,便可插入正文内容,键<a>、<i>和<o>的作用如下:

<a>:

从当前光标所在位置的下一个字符处开始插入新输入内容。

<i>:

从当前光标所在位置开始插入新输入内容。

<o>:

在当前光标所在行下方新增一行,并将光标移到下一行的开始处插入新输入内容。

2、删除

(1)删除一个字符

若要删除文档中的一个字符,可按键<Del>,其作用是删除当前光标位置的字符。

(2)删除一行

若要删除文档中某一行的内容,可先将光标移到该行,然后在命令模式下,按键<d><d>(即按两次d键)。

3、替换

若要替换修改文档中的内容,可在命令模式下,按键<R>,切换到输入模式的替换状态,其作用如下:

<R>:

从命令模式切换到输入模式的替换状态,新键入的正文内容将替换原光标处的文本内容。

4、剪切、复制与粘贴

(1)一行正文的复制

若要复制光标所在行,可在命令模式下,按键<y><y>,其功能如下:

<y><y>:将光标所在行的文本复制到缓冲区。

(2)一行正文的剪切

若要剪切光标所在行,可在命令模式下,按键<c><c>,其功能如下:

<c><c>:将光标所在行的文本剪切到缓冲区。

(3)正文块的设置

若要对正文中某一区域内容进行复制或剪切操作,则可将这一区域内容先标记为块,标记的方法如下:

首先,将光标移至块的首字符下,在命令模式下,按键<v>,切换到输入模式的“VISUAL”状态;

然后,用方向键(↓、→)移动光标到所要设置区域的尾部,块以高亮度呈现。

(4)正文块的复制

若要复制正文块内容,在输入模式的“VISUAL”状态下,按键<y>,其功能如下:

<y>:将正文块内容复制到缓冲区中。

(5)正文块的剪切

若要剪切正文块,可在输入模式的“VISUAL”状态下,按键<d>,其功能如下:

<d>:将正文块内容剪切到缓冲区中。

(6)粘贴

若要将缓冲区的内容粘贴到指定的位置,可在命令模式下,按键<P>或<p>。按键<P>和<p>的功能如下:

<P>:

将缓冲区中的内容粘贴到当前光标字符位置的前面。

<p>:

将缓冲区中的内容粘贴到当前光标字符位置的后面。

5、恢复与撤消

(1)撤消

若要撤消上一次的操作,可在命令模式下,按键<u>。按键<u>的功能如下:

<u>:

撤消上一次的操作。

(2)恢复

恢复是指对撤消操作的恢复操作。若要恢复撤消操作,可在命令模式下,按键<Ctrl>+<R>,按键<Ctrl>+<R>的功能如下:

<Ctrl>+<R>:

恢复上一次撤消操作。

3.4 查询操作

1、查找

当需要在正文中搜索指定的字符串,可在底行命令模式的提示符下,键入下列搜索命令:

命令

功能

/<字符串>:

从当前光标位置向后寻找这个字符串。

?<字符串>:

从当前光标位置往前寻找这个字符串。

n:

重复上一个/或?命令指令,继续寻找。

N:

重复上一个/或?的指令,反向继续寻找。

2、查找与替换

若在查找字符串的同时,用另一字符串替换它,这就是查找与替换操作。当需要对正文进行查找与替换操作时,可在底行命令模式下,使用命令查找与替换命令,命令格式如下:

[n1,n2]s  /字符串1  /字符串2  [/gc]

其功能是在“n1,n2”指定的行范围中,查找字符串1,找到后,用字符串2替换。

选项说明:

n1,n2:指定从第n1行起到第n2行至的范围中进行查找和替换,缺省时,只对当前行进行查找与替换操作。

/g:表示对行中所有出现的字符串1均用字符串2替换,缺省时,只在行中出现的所有字符串1,只替换第一个。

/c:表示替换前让用户确认。

例如,若要对当前文档中的所有字符串“student”替换成“Student”,且在每一个替换前让用户确认一下,则键入命令“1,n  s/student/Student/gc”(其中,n表示最后一行的行号)。

【实习报告】

实习报告:Linux vi的使用

学生姓名:       班级:        学号:

一、实习内容(完成的内容截图说明)

1、用vi编辑器建立一个文件exec,文件内容如下:

The present economic system of production,distribution and consumption consumed many years in the making.

2、在exec文件的第一行后插入如下两行内容:

when the profits were alloted, I received one-hundred dollars.

Wet days alternated with fien days.

3、将文件中第二行中的单词“when”的第一个字符“w”改写成大写“W”。

4、将光标移到单词“fien”上,修改成“fine”。

5、查找到单词“alloted”,删除该单词,重新打入单词“allotted”。

6、用“查找”和“替换”命令实现,用“100”替换单词“one-hundred”。

7、在文件的第四行上复制第二行的内容。

8、将文件中第一行内容移至文件尾。

9、分别用cat 命令或more命令检查编辑修改后的exec文件。

10、将exec文件中的第一行内容写成文件exec1,存于当前目录下。

11、如何获得有关vi编辑器的帮助信息?

12、在exec文件的开始处,插入exec0文件(文件exec0是事先在当前目录下已创建的文件文件)内容。

二、实习总结

 

Unit 4  Linux shell编程

【实习要求】

掌握Linux shell的基本编程

    包括:编程、调试与应用

【实习内容】

Linux shell编程

【实习指导】

4.1 shell编程简介

Linux shell是一个命令解释器,用来接受并执行命令(包括运行批处理文件和执行程序)。shell环绕在内核的外层,它是Linux操作系统和用户之间的界面。当用户从shell或其他程序向Linux传递命令,内核会做出相应的反应。

这里,将介绍Linux下最常用的shell —— bash。bash(Bourne Again Shell)是大多数Linux发行套件的缺省shell,并被大多数用户所使用。

在命令行输入命令时,每次输入一个命令,就可得到系统的响应。但如果经常要依次执行同一组命令,就可以利用shell程序来实现。shell程序是放在一个文件中的一系列的Linux命令。执行shell程序时,由Linux逐条解释和执行每个命令。

4.1.1 shell程序文件

shell程序文件是一个特殊的文本文件,其内容包含一系列可在shell提示符下执行的命令,以及shell提供的专用的命令和控制语句。Linux提供的shell命令可通过命令help来获得,在shell提示符下,键入命令“help | more”,图4-1所示是获得所有shell命令的列表的一部分。

图4-1

如要获得其中命令echo的详细帮助信息,则在shell提示符下,键入命令“help  echo”,便获得该命令的详细使用信息如图4-2所示。

图4-2

图中可观察到,该命令的功能是在屏幕上输出给定的信息。

shell程序文件的运行过程是将shell程序文件中的命令依次执行。

4.1.2 shell程序的建立

shell程序文件可用任何一个文件编辑器(如vi)来建立。

例如,建立shell程序shex1,存放在当前目录下(假定当前目录为 /root),程序功能为先清屏,然后显示98年的1、2、3月份的月历。程序文件内容如下:

clear

cal  1  98

cal  2  98

cal  3  98

用vi编辑器建立shell程序文件shex1的方法如下:

(1)键入命令“vi  shex1”,启动vi;

(2)按命令“i”,进入vi的插入状态;

(3)输入程序文件内容;

(4)按<Esc>键,再键入“:”,切换到vi的命令状态;

(5)最后键入命令“wq”,保存文件内容后,退出vi。

至此,shell程序文件shex1已建立。

4.1.3 shell程序的运行

运行shell程序有两种方法:一种是在shell环境下,将shell 程序文件作为子shell程序被调用执行;另一种是将shell程序文件视作命令来执行(因此,shell程序文件可以看作是将各种命令组合在一起而形成的新命令),此时必须赋予shell程序文件执行权限。

方法一:sh  <shell程序文件名>  [<参数1>  <参数2>  ……]

方法二:<shell程序文件名>  [<参数1>  <参数2>  ……]

例如,分别用两种方法运行已建立的shell程序文件shex1。

方法一:

在shell提示符下,键入命令:“sh  shex1”。

方法二:

(1) 首先,给shell程序文件shex1赋予可执行权限,则在shell提示符下,键入命令:“chmod  a+x  shex1”;

(2)然后,在shell 提示符下,键入命令“/root/shex1”便可执行该shex1程序,如同其他shell命令一样。

两种方法的运行结果,如图4-3所示。

图4-3

运行命令中有[参数]和没有[参数]的情况分别称为带参数的运行命令和不带参数的运行命令。在shell程序中可使用的形参为$0、$1、$2、……$9,当程序运行时,<参数1>  <参数2>  ……依次赋值给$1、$2、……,通常称运行命令中所带的参数为实参。

$0是一个特殊的形参,其值规定为当前运行的shell程序命令本身。

由于形参个数有限,当参数较多时,可通过命令shift来移动形参与实参的对应关系,执行一次shift后,$1、$2、……变为依次与<参数2>  <参数3>……对应,再执行一次shift后,$1、$2、……变为依次与<参数3>  <参数4>……对应,依此类推。通过下面的例子shell程序shex2,可观察参数的移动变化。

shex2程序文件内容如下:

echo  $0  $1  $2

shift

echo  $0  $1  $2

运行的命令所带参数及运行结果如图4-4所示。

图4-4

图中可观察到,$0的值始终是当前运行的shell程序命令本身,即 /root/shex2。

例如,将shex1程序用参数形式进行改写,程序功能保持不变,最后将程序保存为shex3,存放在当前目录下。

shex3程序文件内容如下:

clear

cal  $1  98

cal  $2  98

cal  $3  98

运行的命令所带参数及运行结果分别如图4-5所示。

图4-5

当带参数的运行命令为“/root/shex3  1 2 3”,则运行结果显示如图4-3所示。注意,当实参为空时,形参将被传递空值。

4.1.4 shell变量

Linux 的shell程序中允许使用各种类型的变量,主要有系统、内部和用户变量三种。

系统变量也称环境变量,它与用户变量的区别在于它可将值传给shell运行的其他命令或shell程序使用,亦即系统变量是全局变量。

内部变量是由系统提供,与环境变量不同,用户不能修改

用户变量由用户定义的变量,是当前shell的局部变量,不能被shell运行的其他命令或shell程序使用,亦即用户在shell程序中定义的程序变量只在程序运行时有效,一旦退出,这些变量自动失效。

通过shell提供的命令set,可以查看当前shell下定义的一系列变量及其值。例如,在shell提示符下,键入命令“set | more”,显示当前shell下定义的变量及其值如图4-6所示。

图4-6

1、变量赋值

格式:<变量名> =<字符串>

功能:将等号右边的字符串赋给等号左边的变量,即右边的字符串为左边变量的值。

说明,任何不含空格的字符串都可作变量名。若字符串中含有空格,则在字符串上加上引号。

例如,要求定义一个用户变量name1,并给变量赋值为“MARY”,则在shell提示符下,键入命令“name1=MARY”。

例如,要求定义一个用户变量 name2并给变量赋值为“X Window”,则在shell提示符下,键入命令“name2="X Window"”。

2、引用变量

格式:$<变量名>

功能:引用变量的值。

例如,要求将变量name1的值赋给变量name2,则在shell提示符下,键入命令“name2=$name1”。

例如,要求在屏幕上显示变量name1的值,则在shell提示符下,键入命令“echo  $name1”。

3、释放变量

格式:unset  <变量名>

功能:释放一个现存的shell变量。

例如,要求释放变量name1,则在shell提示符下,键入命令“unset  name1”。变量的定义、赋值及引用过程如图4-7所示。

图4-7

4.1.5 shell程序的控制流

与其他高级语言一样,shell编程中也提供了条件与循环等控制结构,下面介绍bash提供的主要的程序控制结构语句。

1、条件控制流

(1)if-then-else 结构

 if  <条件判断命令>

  then  <命令集1>

  else  <命令集2>

         fi

其中,<条件判断命令>通常是“test  <表达式>”,当条件成立,则返回0;条件不成立,则返回一个非0值。

执行过程说明:当<条件判断命令>返回0时,则执行then后的<命令集1>,然后执行fi后面的命令;否则执行else 后的<命令集2>,然后执行fi后面的命令。在if-then-else结构中,允许在then和else后的命令集中包含if-then-else结构,即允许嵌套。

需要强调的是其中if和fi必须配对出现。

(2)if-then-fi结构

 if  <条件判断命令>

  then  <命令集>

 fi

执行过程说明:当<条件判断命令>返回0时,则执行then后的<命令集>,然后执行fi后面的命令,否则执行fi后面的命令。

(3)case结构

case  <变量>  in

字符串1)  <命令集1>

        ;;

字符串n)  <命令集n>

       *)  <缺省命令>

esac

其中,字符串中可含通配符。

执行过程说明:程序将<变量>的值依次和字符串1、字符串2、……、字符串n进行比较,哪个匹配,则执行后面的<命令集>;若都不匹配,则执行<缺省命令>。

说明,如果能同时匹配多个字符串,则只能执行第一个匹配字符串后的<命令集>。

2、循环控制流

(1)for-in结构

for  <循环变量>  [in  <循环变量取值集>]

  do

    <命令集>

          done

       其中,<循环变量取值集>中的值与值之间用空格分隔。

执行过程说明:程序从<循环变量取值集>中依次取值,赋给<循环变量>,并执行一轮由do和done括起来的循环体中的<命令集>,直到<循环变量取值集>中的值取完,再执行done后面的命令。

若“in  <循环变量取值集>”缺省,则<循环变量取值集>为实参集。

(2)while 结构

 while  <条件判断命令>

  do

    <命令集>

          done

执行过程说明:当<条件判断命令>返回0时,则执行一轮由do和done括起来的循环体中的<命令集>,直到<条件判断命令>返回一个非0值时,则不再执行循环体中的命令,执行done后面的命令。

(3)until 结构

until  <条件判断命令>

  do

    <命令集>

          done

执行过程说明:与while 结构相反,当<条件判断命令>返回非0时,执行循环体中的命令,直到<条件判断命令>返回一个0值时,,继续执行done后面的命令。

3、条件判断命令test

条件表达式是控制程序流程的关键,shell提供的test命令可组合多个表达式,生成功能灵活的条件表达式,使shell程序的功能更强,下面介绍test命令的基本使用。

格式:

test  <表达式>

功能:test命令返回表达式成立与否的状态值,如果表达式成立,则test返回真的状态值0,否则,test返回假的状态值,即一个非0值。test命令中的<表达式>常见的有以下几类:

(1)文件特性类

-e  <文件名>:

    检查<文件名>存在否,若存在,返回真值;否则返回假值。

-f  <文件名>:

    检查<文件名>是否是普通文件,若是,返回真值;否则返回假值。

-d  <文件名>:

    检查<文件名>是否是目录,若是,返回真值;否则返回假值。

-r  <文件名>:

    检查<文件名>是否可读,若是,返回真值;否则返回假值。

-w  <文件名>:

    检查<文件名>是否可写,若是,返回真值;否则返回假值。

-x  <文件名>:

    检查<文件名>是否可执行,若是,返回真值;否则返回假值。

-s  <文件名>:

    检查<文件名>是否存在且文件长度大于零,若是,返回真值;否则返回假值。

<文件名1>  –nt  <文件名2>:

    如果<文件名1>比<文件名2>新(根据文件最后修改时间判断),返回真值;否则返回假值。

<文件名1>  –ot  <文件名2>:

    如果<文件名1>比<文件名2>旧(根据文件最后修改时间判断),返回真值;否则返回假值。

<文件名1>  –ef  <文件名2>:

    如果<文件名1>和<文件名2>有相同的设备名和inode号,返回真值;否则返回假值。

(2)字符串类

-z  <字符串>:

    如果<字符串>长度为零,返回真值;否则返回假值。

-n  <字符串>:

    如果<字符串>长度不为零,返回真值;否则返回假值。

<字符串1>  =  <字符串2>:

    如果<字符串1>与<字符串2>相等,返回真值;否则返回假值。

<字符串1>  !=  <字符串2>:

    如果<字符串1>与<字符串2>不相等,返回真值;否则返回假值。

(3)与或表达式类

!<表达式>:

    如果<表达式>为假,则返回真值;否则返回假值。

<表达式1>  –a  <表达式2>:

    <表达式1>、<表达式2>进行与操作,若<表达式1>、<表达式2>均为真,则返回真值;否则返回为假值。

<表达式1>  –o  <表达式2>:

    <表达式1>、<表达式2>进行或操作,若<表达式1>、<表达式2>均为假,则返回假值;否则返回真值。

(4)数值表达式类

<数值表达式1>  –eq  <数值表达式2>:

    如果<数值表达式1>等于<数值表达式2>,则返回真值;否则返回假值。

<数值表达式1>  –ne  <数值表达式2>:

    如果<数值表达式1>不等于<数值表达式2>,则返回真值;否则返回假值。

<数值表达式1>  –lt  <数值表达式2>:

    如果<数值表达式1>小于<数值表达式2>,则返回真值;否则返回假值。

<数值表达式1>  –le  <数值表达式2>:

    如果<数值表达式1>小于或等于<数值表达式2>,则返回真值;否则返回假值。

<数值表达式1>  –gt  <数值表达式2>:

    如果<数值表达式1>大于<数值表达式2>,则返回真值;否则返回假值。

<数值表达式1>  –ge  <数值表达式2>:

    如果<数值表达式1>大于或等于<数值表达式2>,则返回真值;否则返回假值。

4.2 shell程序调试简介

有两种简便的跟踪功能可以用于shell程序的调试,即在shell程序中加入命令set  -v或set  -x。

格式1:set  -v

功能:当执行一个shell程序时,会在执行程序文件中的每条命令之前,自动在屏幕上先显示该条命令。

格式2:set  -x

功能:当执行shell程序时,它会把将要执行的命令逐条进行参量定值,并以最后执行的形式在屏幕上显示。

4.3 实例

1、编写shell程序文件shp1,存放在当前目录下,程序功能要求如下:

如果 /etc目录中的文件profile存在,则将其复制到fd0盘的根目 录中,并分屏显示fd0盘上的profile文件内容;否则在屏幕上显示信息“profile is not exist!”。

(1)用vi创立shell程序文件shp1,程序如下:

if  test  -e  /etc/profile

 then  cp  /etc/profile  /mnt/floppy

       cat  /mnt/floppy/profile|more

       rm  -f  /mnt/floppy/profile

 else  echo  profile  is  not  exist!

fi

(2)用两种方法运行程序shp1

方法一:

在shell提示符下,键入命令“sh  shp1”。

方法二:

①给程序文件赋予可执行属性“X”

  在shell提示符下,键入命令“chmod  a+x  shp1”

       ②运行程序

  在shell提示符下,键入命令“/root/shp1”

观察运行结果,若文件profile存在,则屏幕显示如图4-8所示 ,若文件profile不存在,则屏幕显示如图4-9所示。

图4-8

图4-9

2、编写shell程序文件shp2,存放在当前目录下,程序功能要求如下:

用for命令实现,在当前目录下创建名为user0、user1、user2、……user9十个子目录后,用长格式显示这十个目录的目录信息,然后用for命令删去这十个目录后,再用长格式显示这十个目录的目录信息。

(1)用vi创立shell程序文件shp2,程序如下:

for  i  in  0 1 2 3 4 5 6 7 8 9

 do  mkdir  user$i

 done

ls  -dl  user?|more

for  i  in  0 1 2 3 4 5 6 7 8 9

 do  rm  -rf  user$i

 done

ls  -dl  user? | more

(2)用两种方法运行程序shp2

方法一:

在shell提示符下,键入命令“sh  shp2”。

方法二:

①给程序文件赋予可执行属性“X”

  在shell提示符下,键入命令“chmod  a+x  shp2”

②运行程序

  在shell提示符下,键入命令“/root/shp2”

观察运行结果,屏幕显示如图4-10所示。

图4-10

3、编写shell程序文件shp3,存放在当前目录下,程序功能要求如下:

如果shp3运行时未带参数,则在屏幕上显示信息“Parameter  Lost!”,并结束程序运行;如果shp3运行时带一个参数,则判断参数所指定的文件是否存在,如果存在则复制该文件到fd0盘的根目录;否则先在屏幕上显示信息“File  not  found!”,然后显示程序自身。

(1)用vi创立shell程序文件shp3,程序如下:

if  test  -z  $1

 then  echo  Parameter Lost!

 else  if  test  -e  $1

        then  cp  $1  /mnt/floppy

        else  echo  File  not  found!

              cat  $0

       fi

fi

(2)用两种方法运行程序shp3

方法一:

在shell提示符下,键入命令“sh  shp3”。

方法二:

① 给程序文件赋予可执行属性“X”

  在shell提示符下,键入命令“chmod  a+x  shp3”

② 运行程序

  在shell提示符下,键入命令“/root/shp3”

测试并观察程序运行结果,若键入命令“sh  shp3”,则运行结果显示如图4-11所示;若键入命令“sh  shp3  shp1”,则运行结果显示如图4-12所示;若键入命令“sh  shp3  sx”(其中,sx参数所指定的文件是一个不存在的文件),则运行结果显示如图4-13所示。

图 4-11

图 4-12

图 4-13

4、编写shell程序文件shp4,存放在当前目录下,程序功能要求如下:

如果shp4运行时未带参数,则在屏幕上显示信息“ERROR1”;如果shp4运行时只带一个参数,则在屏幕上显示信息“ERROR2”;如果带两个不同的参数且参数1所指定的文件存在,则将参数1所指定的文件复制到fd0盘的根目录中,并改名为参数2所指定的文件名。

(1)用vi创立shell程序文件shp4,程序如下:

if  test  -z  $1

  then  echo  ERROR1

  else  if  test  -z  $2

         then  echo  ERROR2

         else  if  test  $1  !=  $2  -a  -e  $1

                then  cp  $1  /mnt/floppy/$2

               fi

        fi

fi

(2)用两种方法运行程序shp4

方法一:

在shell提示符下,键入命令“sh  shp4”。

方法二:

① 给程序文件赋予可执行属性“X”

  在shell提示符下,键入命令“chmod  a+x  shp4”

② 运行程序

  在shell提示符下,键入命令“/root/shp4”

测试程序,若键入命令“sh  shp4  shp1  test1”、“cat  shp1”、“cat  /mnt/floppy/test1”,则运行结果显示如图4-14所示。

图4-14

图中可观察到,fd0盘上的复制文件的内容te

sst1与原文件shp1的内容完全一致。

5、编写shell程序文件shp5,存放在当前目录下,程序功能要求如下:

① 清屏

② 当程序运行时,屏幕显示如下形式的信息:

*********************************************************************

* This  is  a  shell  program  for  renaming  and  ...*

*********************************************************************

③ 检查在fd0盘的根目录中,是否存在由参数1指定的文件,若不存在,则屏幕显示信息“File  not  found!”;若存在则将参数1指定的文件改名为由参数2指定的文件名,然后用for命令对改名后的文件显示长格式的目录信息和文件内容。

(1)用vi创立shell程序文件shp5,程序如下:

clear

echo  "***********************************************"

echo  "* This is a shell program for nameing ... *"

echo  "***********************************************"

if  test  -n  $1  -a  -n  $2

 then  if  test  $1  !=  $2

        then  if  test  -e  $1

               then  mv  $1  $2

                     for  cn  in  "ls -l"  "cat" 

                      do

                       $cn  $2

                       echo " "

                      done

              fi

        else  echo  File  not  found!

       fi

fi

(2)用两种方法运行程序shp5

方法一:

在shell提示符下,键入命令“sh  shp5”。

方法二:

① 给程序文件赋予可执行属性“X”

  在shell提示符下,键入命令“chmod  a+x  shp5”

② 运行程序

  在shell提示符下,键入命令“/root/shp5”

测试程序,若键入命令“/root/shp5  shp1  abc”,观察到的运行结果如图4-15所示。

图4-15

6、编写shell程序文件shp6,存放在当前目录下,程序功能要求如下:

运行程序shp6时带一个正整数参数,将参数值存入变量value中,如果该参数大于等于1但小于3,则在屏幕上显示信息“Value is less than 3 and not less than 1.”;如果该参数大于等于3,则在屏幕上显示信息“Value is not less than 3.”;最后以“value=xx”的形式显示变量value的值。

(1)用vi创立shell程序文件shp5,程序如下:

if  test  $1  -ge  1  -a  $1  -lt  3

 then  value=$1

       echo  value  is  less  than  3  and  not  less  than 1

fi

if  test  $1  -ge  3

 then  value=$1

       echo  value  is  not  less  than  3

fi

echo  value=$value

(2)用两种方法运行程序shp6

方法一:

在shell提示符下,键入命令“sh  shp6”。

方法二:

① 给程序文件赋予可执行属性“X”

  在shell提示符下,键入命令“chmod  a+x  shp6”

② 运行程序

  在shell提示符下,键入命令“/root/shp6”

测试程序并观察运行结果如图4-16所示。

图4-16

7、编写shell程序文件shp7,存放在当前目录下,程序功能要求如下:

如果shell程序文件的文件名不为test0,并且当前目录中不存在test0文件,则将本shell程序文件的名字改为test0,若当前目录中存在test0文件,则先删除,再将本shell程序文件的名字改为test0。

(1)用vi创立shell程序文件shp7,程序如下:

echo  Filename  must  be  test0.

if  test  $0  !=  test0

 then

  if  test  -e  test0

    then  rm  -f  test0

  fi

  mv  $0  test0

fi

(2)用两种方法运行程序shp7

方法一:

在shell提示符下,键入命令“sh  shp7”。

方法二:

① 给程序文件赋予可执行属性“X”

  在shell提示符下,键入命令“chmod  a+x  shp7”

② 运行程序

  在shell提示符下,键入命令“/root/shp7”

测试程序并观察运行结果显示如图4-17所示。

图4-17

8、编写shell程序文件shp8,存放在当前目录下,程序功能要求如下:

判断fd0盘的根目录下是否存在子目录dir1和dir2,若不存在,则先建立它们;若存在,则分别删除目录下的文件dlist和flist。然后将/home目录下所有目录文件的目录信息,以长格式形式保存到fd0盘的dir1子目录下的文件dlist中;将/home目录下的所有文件的目录信息,以长格式形式保存到fd0盘的dir2子目录下的文件flist中。

(1)用vi创立shell程序文件shp8,程序如下:

if  test  !  -d  /mnt/floppy/dir1

 then  mkdir  /mnt/floppy/dir1

 else  rm  -f  /mnt/floppy/dlist

fi

if  test  !  -d  /mnt/floppy/dir2

 then  mkdir  /mnt/floppy/dir2

 else  rm  -f  /mnt/floppy/flist

fi

ls  -dl  /home  > /mnt/floppy/dir1/dlist

ls  -l  /home  > /mnt/floppy/dir2/flist

(2)用两种方法运行程序shp8

方法一:

在shell提示符下,键入命令“sh  shp8”。

方法二:

① 给程序文件赋予可执行属性“X”

  在shell提示符下,键入命令“chmod  a+x  shp8”

② 运行程序

  在shell提示符下,键入命令“/root/shp8”

测试程序并观察运行结果显示如图4-18所示。

图4-18

9、编写shell程序文件shp9和sub1,存放在当前目录下,程序完成以下功能:

shp9作为shell程序文件的主文件,sub1作为shell程序文件的子文件,当shp9调用sub1时传递两个参数,参数1为文件权限属性,参数2为指定用户,sub1的功能是将当前目录下以小写字母开头且文件名长度为2的所有文件,为指定用户设置指定的权限属性。

(1)用vi创立shell程序文件shp9和sub1,shp9程序如下:

sh  sub1  r  u

sh  sub1  w  g

sh  sub1  x  o

ls  -l  [a-z]?

键入sub1程序如下:

chmod  $2=$1  [a-z]?

(2)用两种方法运行程序shp9

方法一:

在shell提示符下,键入命令“sh  shp9”。

方法二:

① 给程序文件赋予可执行属性“X”

  在shell提示符下,键入命令“chmod  a+x  shp9”

② 运行程序

  在shell提示符下,键入命令“/root/shp9”

测试并观察程序运行结果显示如图4-19所示。

图4-19

10、编制一个shell程序文件shp10,当以命令“shp10  xx  yy”执行shell程序时(其中,xx为年份参数,yy为季度参数),能自动清屏,并显示指定年份指定季度中的三个月的月历。

(1)用vi编辑器编辑建立shell程序文件shp10,程序如下:

clear

k=$2

if  test  $k=1

  then  cal  1  $1

        cal  2  $1

        cal  3  $1

fi

if  test  $k=2

  then  cal  4  $1

        cal  5  $1

        cal  6  $1

fi

if  test  $k=3

  then  cal  7  $1

        cal  8  $1

        cal  9  $1

fi

if  test  $k=4

  then  cal  10  $1

        cal  11  $1

        cal  12  $1

fi

(2)用两种方法运行程序shp10

方法一:

在shell提示符下,键入命令“sh  shp10”。

方法二:

① 给程序文件赋予可执行属性“X”

  在shell提示符下,键入命令“chmod  a+x  shp10”

② 运行程序

  在shell提示符下,键入命令“/root/shp10”

测试并观察程序的运行结果如图4-20所示。

图4-20

11、编制一个shell程序shp11,当用命令“shp11  xx  yy  ...”执行程序 shp11时(其中,xx yy …为一系列指定文件的参数),要求能判断由参数指定的每个文件是否存在,若不存在,则在屏幕上显示信息“file not exists”;如果文件存在,则进一步判断文件长度是否为零,若文件长度为零,则屏幕显示信息“file exists and has a size equal zero”,否则显示信息“file exists and has a size greater then zero”。

(1)用vi编辑器建立shell程序文件shp11,用while循环结构编制shp11程序如下:

while  test  $1

 do

  If  test  -e  $1

    then  if  test  -s  $1

           then  echo  file $1 exists and has a size greater than zero.

           else  echo  file $1 exists and has a size equal zero.

          fi

    else  echo  file $1  not  exists.

  fi

  shift

 done

用until循环结构编制shp11程序如下:

until  test  -z  $1

 do

  if  test  -e  $1

    then  if  test  -s  $1

           then  echo  file $1  exists and has a size greater than zero.

           else  echo  file $1  exists and has a size equal zero.

          fi

    else  echo  file $1  not exists.

  fi

  shift

 done

(2)建立一个长度为零的文件f1,用命令“sh  shp11  f1”执行程序shp11,测试程序的正确性,屏幕显示如图4-21所示。

图4-21

【实习报告】

实习报告:Linux shell编程

学生姓名:       班级:        学号:

一、完成shp11-shp11练习并完成以下内容

二、实习内容

1、编写shell程序文件sht1,存放在当前目录下,程序功能要求如下:

(1)清屏

(2)当程序运行时,屏幕显示如下形式的信息:

    ****************************

       *  Hello  World!  ...*

    ****************************

2、编写shell程序文件sht2,存放在当前目录下,程序功能要求如下:

用for命令结构实现,检查当前目录下文件f1、f2、f3、f4、f5,若长度为零则删除它(删除时,不需要用户确认)。

3、编写shell程序文件sht3,存放在当前目录下,程序功能要求如下:

(1)检查fd0盘根目录下,是否存在文件fd0tree,存在则删除它;

(2)用一条命令,在fd0盘根目录下建立名为temp0、temp1、……、tmep9的十个子目录;

(3)以fd0盘根目录为起点的目录树图形结构组成一个可观察文件fd0tree,存放到fd0盘的根目录中;

(4)用一条命令,将fd0盘根目录下的temp0、temp1、……、temp9十个子目录删除;

(5)将以fd0盘根目录为起点的目录树图形结构,添加到fd0盘根目录下文件fd0tree的尾部。

4、编写shell程序文件sht4,存放在当前目录下,程序功能要求如下:

运行程序sht4时带一个正整数参数,如果该正整数大于等于1但小于等于5,则在屏幕上显示信息“Value is not more than 5 and not less than 1.”;如果该参数大于5,则在屏幕上显示信息“Value is more than 5.”。

5、编写shell程序文件sht5和sub2,存放在当前目录下,完成如下功能:

sht5作为shell程序文件的主文件,sub2作为shell程序文件的子文件,由sht5调用sub2完成自动在fd0盘根目录下建立USER00、USER01、……、USER99一百个子目录。

6、将上机实践中的shell程序文件shp10用case结构进行改写为shell程序文件sht6,程序功能不变。

三、实习总结

Unit5  Linux C编程

【实习要求】

1、掌握Linux C的基本编程与调试

     包括:编程与调试

2、掌握Linux C程序与OS的传递参数

【实习内容】

Linux C编程

【实习指导】

5.1 程序的编辑与编译

1、源程序的编辑

Linux中,C源程序可使用Linux的编辑器vi,或Emacs进行编写。

2、源程序的编译

在Linux中,gcc(GNU C Compiler)是C、C++、ObjectiveC源程序的编译器,gcc编译C源程序并生成可执行文件要经过以下四步:

(1)预处理

gcc编译器调用cpp程序,对各种命令如 #define、#include、#if 进行分析。

(2)编译

gcc编译器调用ccl程序,根据输入文件产生中间文件。

(3)汇编

gcc编译器调用as程序,用中间文件作为输入产生以o作为类型名的目标文件。

(4)连接

gcc编译器调用 ld程序,将各目标程序组合于可执行文件中的适当位置,这一程序引用的函数也放在可执行文件中。

gcc编译器的命令格式如下:

gcc  [options] [filename]…

常用选项的说明:

-c:对源程序进行预处理、编译,产生目标文件,但不进行连接。

-o  <文件名>:定义输出的执行文件名为<文件名>。

-S:在编译后停止,产生类型名为s的汇编代码文件,不生成中间文件。

-E:在预处理后停止,输出预处理后的源代码至标准输出,不进行编译。

-O:对程序编译进行优化,减少被编译程序的长度和执行时间,但此时的编译速度比不作优化慢且要求较多的内存。

-g:产生一张用于调试和排错的扩展符号表,此选项使程序可用gdb进行调试。

-lobjc:可用于连接类型名为o的目标文件生成可执行文件。 

3、程序的运行

经调试排错后的目标程序即可正常运行,并产生应有的正确结果。运行目标程序的方法是在shell提示符下,键入目标程序的绝对路径和目标程序名。

5.2 程序的调试

5.2.1 gdb简介

当编译后得到的目标程序在运行时出现故障,或运行的结果与我们的预期不一致,我们通常称程序发生了运行错误,或逻辑错误。这时,需要对源程序进行调试以找出错误,排除故障。Linux提供了调试源程序的工具gdb(GNU debugger),gdb不仅允许用户在运行程序时显示源代码,而且在调试过程中允许在预设的断点处暂停程序的运行,显示变量的内容。下面介绍 gdb的基本使用方法。

1gdb的启动与退出

在shell提示符下,键入命令 “gdb  <文件名>”,则启动gdb并运行由<文件名>指定的目标程序文件,并给出gdb的提示符:(gdb)。

在gdb的提示符下,键入命令“q”(或quit),退出gdb。

       启动和退出gdb的过程如图5-1所示。

图5-1

2gdb中的常用命令如表5-1所示。

5-1  gdb中的常用命令

命令

功能

r(或run)

运行程序。

p  <变量>(或print <变量>)

显示变量内容。

p  &<变量>(或print &<变量>)

显示变量地址。

set  <变量>=<值>

对变量赋值。

where

显示函数的调用情况及使用的参数。

info  locals

显示已定义的变量和参数。

l  <行号>(或list  <行号>)

显示指定行号开始的源代码。

l  <函数>(或list  <函数>)

显示函数中的源代码。

l  <数字>,<数字>

(或list  <数字>  <数字>)

显示指定行号范围内的源代码。

n和s(或next和step)

单步执行程序。

c(或cont)

继续执行程序。

b(或break)

在当前行设置断点。

b  <行号>(或break  <行号>)

在指定的行设置断点。

b  <函数>(或break  <函数>)

在指定函数的第一行设置断点。

info  break

列出所有的断点。

d(或delete)

删除所有断点。

d  <数字>

删除指定断点号的断点。

注意:在使用gdb调试程序前,必须使用gcc - g对源程序进行编译。

5.2.2 调试实例

1、建立C源程序文件star.c,程序内容如下:

main()

{

  int i=0;

  do{

     printf("*");

     ++i;

 }while(i<10);

     printf("\n");

   }

用vi编辑器建立c源程序文件star.c的方法如下:

(1)键入命令“vi  star.c”,启动vi;

(2)按命令“i”,进入vi的插入状态;

(3)输入程序内容;

(4)按<Esc>键,再键入“:”,切换到vi的命令状态;

(5)最后键入命令“wq”,保存文件内容后,退出vi。

至此,c源程序文件star.c已建立。

2、编译程序star.c,其目标程序以star命名且可用gdb进行调试

调试方法如下:

(1)对源程序进行编译,在Shell提示符下,键入命令“gcc  -g  star.c  -o  star”,屏幕提示如图5-2所示。

图5-2

(2)如果出现shell提示符,说明编译成功,此时可用ls命令查看当前目录,可看到目标程序文件star。如图5-3所示。

图5-3

3、使用gdb调试工具监视程序执行

跟踪调试的方法如下:

(1)启动gdb并运行程序star。在shell提示符下,键入命令“gdb star”,出现gdb的提示符(gdb)如图5-4所示。

图5-4

(2)在(gdb)提示符下。键入命令“l  1,7”,屏幕输出star源程序,如图5-5所示。

图5-5

(3)将断点设在源程序的第5行。在(gdb)提示符下,键入命令“b 5”,如图5-6所示。

图5-6

(4)程序在断点处暂停运行。在(gdb)提示符下,键入命令“r”, 屏幕提示如图5-7所示:

图5-7

(5)在(gdb)提示符下,键入命令“p  i” ,屏幕上显示变量i的值,如图5-8所示。

图5-8

(6)在(gdb)提示符下,键入命令“c”,程序从断点处继续运行至下一断点,重复(5)~(6)的操作至变量i的值为3。如图5-9所示。

图5-9

(7)在(gdb)提示符下,键入命令“info break”,屏幕显示出所有设置的断点,如图5-10所示。

图5-10

(8)在(gdb)提示符下,键入命令“d”,屏幕提示如图5-11所示。

图5-11

(9)在(gdb)提示符下,键入命令“info break”,屏幕提示没有断点,如图5-12所示。

图5-12

(10)在(gdb)提示符下,键入命令“c” ,程序一直运行到结束,屏幕上输出程序的运行结果,如图5-13所示。

图5-13

(11)在(gdb)提示符下,键入命令“q”,退出gdb。

5.3 程序与OS间的参数传递

通常情况下,主函数main不带任何参数,形式为main()。带参数的main函数的原型如下:

main(int argc, char * argv[]);

main函数是由操作系统调用的,因此当需要在系统与程序间传递信息时,可通过这二个形参来完成。操作系统命令行的一般形式为:

命令名  参数参数参数3 ……参数n

从命令行,我们可以看出是由一组字符串组成,因此main函数的形参指针数组argv中的元素argv[0]指向字符串“命令名”,argv[1]指向字符串“参数1”,……,形参argc是命令行中参数的个数。

示例:执行命令“file  shanghai  sspu”(其中file为可执行程序),显示参数的个数与各参数。

#include <stdio.h>

main(int argc, char * argv[])

{

  printf("counts=%d\n",argc);

  whiel (argc>1)

  {

    ++argv;

    printf("%s\n",*argv);

    --argc;

  }

}

命令执行结果,在屏幕上输出如下:

counts=3

shanghai

sspu

【实习报告】

实习报告:Linux C编程

学生姓名:       班级:        学号:

一、实习内容

1、建立C源程序p1.c,程序内容如下:

2、用gcc编译器编译该程序,其目标程序以p1命名且可用gdb进行调试。

3、试运行该程序,用gdb对该程序进行调试,直至产生下图所示的执行结果。

4、编写程序p2,当执行命令“p2  file1  file2”,实现复制文件file1成file2。

二、实习总结

Unit6  Linux设备编程

【实习要求】

1、掌握Linux扬声器设备编程

2、掌握Linux扬声器设备编程的应用――扬声器唱歌

3、掌握软盘、U盘的使用

【实习内容】

1、Linux扬声器设备编程

2、Linux扬声器设备编程的应用

3、软盘、U盘的使用

【实习指导】

6.1 Linux声音设备编程

完成《操作系统原理实验》中“6.4 Linux声音设备编程”实验内容(P160-166)

6.2 Linux扬声器编程的应用

利用扬声器发声的频率,让扬声器唱歌。

1、音调的制作简介

中央C的频率为523.3,D为587.3,E为659.3,F为698.5,G为784.0 …… ,综合如表所示:

6-1 音阶-频率对照表

音阶

频率

音阶

频率

音阶

频率

C0

262

C

523

C1

1047

C0#

277

C#

554

C1#

1109

D0

294

D

587

D1

1175

D0#

311

D#

622

D1#

1245

E0

330

E

659

E1

1319

F0

349

F

698

F1

1397

F0#

370

F#

740

F1#

1480

G0

392

G

784

G1

1568

G0#

415

G#

831

G1#

1661

A0

440

A

880

A1

1760

A0#

466

A#

932

A1#

1865

B0

497

B

988

B1

1976

2、实例扬声器唱歌

(1)小蜜蜂歌谱

| 5 33 | 4 22 | 12 34 | 55 5 |

| 5 33 | 4 22 | 13 55 | 1- |

| 11 11 | 1 23 | 33 33 | 34 5 |

| 5 33 | 4 22 | 13 55 | 1 -|

说明:

① 半音的音长为250毫秒。

② 全音的音长为500毫秒。

③ 二拍的音长为1000毫秒。

(2)程序代码

#include < fcntl.h >

#include < stdio.h >

#include < stdlib.h >

#include < string.h >

#include < unistd.h >

#include < sys/ioctl.h >

#include < sys/types.h >

#include < linux/kd.h >

int main(int argc, char **argv)

{

   int console_fd;  //扬声器设备文件句柄

   int i;           // 循环变量

   int s[ ] = {784,659,659,698,587,587,523,587,659,698,784,784,787};

      //第一句乐句的音阶的频率

   int len[ ] = {500,250,250,500,250,250,250,250,250,250,250,250,500};

      //每一个音阶的发声长度

       // 打开控制台,失败则结束程序

       if ( ( console_fd = open ( "/dev/console", O_WRONLY ) ) == -1 )

       {

         fprintf(stderr, "Failed to open console.\n");

         perror("open");

         exit(1);

       }

      //扬声器开始唱歌

      for (i = 0; i < 13; i++)

      {

        int magical_fairy_number = 1190000/s[i];

        ioctl(console_fd, KIOCSOUND, magical_fairy_number); //发声一个音阶

        usleep(1000 * len[i]);                       //延长响声,即节拍长度

        ioctl(console_fd, KIOCSOUND, 0);   //一个音阶的节拍唱完,停止发声

        usleep(1000 * 50);              // 每个音阶之间的停顿,即不发声延迟

       }//for i 唱下一个音阶

  }//main()

6.4 U盘使用

1、先别插U盘,/sbin/lsmod看是否有usb-storage,如果没有的话,依次执行如下命令:

cd  /lib/modules/2.4.20-8/kernel/drivers/usb

for  v  in  *.o  storage/*.o ;  do  /sbin/insmod  $v ;  done

2、再执行命令:/sbin/lsmod,应该有usbcore、usb-ohci(或usb-uhci,根据主板芯片组而不同)、usb-storage、scsi_mod等。其中usb-storage的状态应该为(unused)。

3、插入U盘,不停的/sbin/lsmod,这期间usb-storage的状态应为Initializing,持续片刻。

4、初始化结束后,/sbin/fdisk -l,应该能看到/dev/sda1设备。这时,执行命令:

mount  /dev/sda1  /mnt/udisk

如果是MSDOS格式,又想看到中文,可以使用命令:

mount -t vfat /dev/sda1 /mnt/udisk -o iocharset=gb2312。

【实习报告】

实习报告:Linux设备编程

学生姓名:       班级:        学号:

一、实习内容

1、Linux扬声器设备编程

      # include <fcntl.h>

      # include <stdio.h>

      # include <stdlib.h>

      # include <string.h>

      # include <unistd.h>

      # include <sys/ioctl.h>

      # include <sys/types.h>

      # include <linux/kd.h>

      // 设定默认值

      # define DEFAULT_FREQ 440             // 设定一个合适的频率

      # define DEFAULT_LENGTH 200          // 200微秒,发声的长度以微秒为单位

      # define DEFAULT_REPS 1               // 默认不重复发声

      # define DEFAULT_DELAY 100            // 同样以微秒为单位

      // 定义一个结构,存储所需的数据

      typedef struct

      {

    int freq;                                 // 期望输出的频率,单位为Hz

         int length;                               // 发声长度,以微秒为单位

         int reps;                                 // 重复的次数

         int delay;                                // 两次发声间隔,以微秒为单位

} beep_parms_t;

// 打印帮助信息并退出

void usage_bail(const char *executable_name)

{

  printf("Usage: \n \t%s [-f frequency] [-l length] [-r reps] [-d delay] \n ",executable_name) ;

  exit(1) ;

}

// 分析运行参数,各项意义如下:

// "-f <以Hz为单位的频率值>"

// "-l <以毫秒为单位的发声时长>"

// "-r <重复次数>"

// "-d <以毫秒为单位的间歇时长>"

 void parse_command_line(char **argv, beep_parms_t *result)

      {

          char *arg0 = *(argv++) ;

          while (*argv)

       {

          if (!strcmp(*argv, "-f" ) )

           {                                                                                                    // 频率

                  int freq = atoi(*( ++argv) ) ;

                  if ( (freq <= 0) || (freq > 10000) )

                    {

                      fprintf(stderr, "Bad parameter: frequency must be from l..10000\n" ) ;

                      exit(1) ;

                     }

                   else

  {

                      result -> freq = freq;

                      argv++;

                      }

                   } else

                     if (!strcmp(*argv, "-l") )

                      {                                     // 发声的时间长度

                          int length = atoi( *(++argv) ) ;

                          if (length < 0)

                          {

                             fprintf(stderr, "Bad parameter: length must be >= 0\n" ) ;

                             exit(1) ;

                      } else  

                           {

                          result -> length = length;

                          argv++;

                           }

                  } else

                      if (!strcmp(*argv, "-r" ) )

                                        {                                        // 重复次数

                          int reps = atoi( * (++argv) ) ;

                          if (reps < 0)

                          {

                              fprintf(stderr, "Bad parameter:reps must be >= 0\n" ) ;

                              exit(1) ;

                          } else

                          {

                              result -> reps = reps;

                              argv++;

                          }

                      } else

                          if (!strcmp(*argv, "-d") )

                                            {                                           // 延时

                              int delay = atoi( * (++argv) ) ;

                              if (delay < 0)

                              {

                                fprintf(stderr, "Bad parameter: delay must be >= 0\n" ) ;

                                 exit(1) ;

                              } else

                              {

                                  result -> delay = delay;

                                  argv++;

                                }

                              } else

                              {

                               fprintf(stderr, "Bad parameter:%s\n" , *argv) ;

                               usage_bail(arg0) ;

                                }

                   }

          }

          int main(int argc, char **argv)

          {

          int console_fd;

          int i;                                                    // 循环计数器

          // 设发声参数为默认值

         beep_parms_t  parms={DEFAULT_FREQ, DEFAULT_LENGTH,

              DEFAULT_REPS, DEFAULT_DELAY} ;

          // 分析参数,可能的话更新发声参数

         parse_command_line(argv, &parms) ;

          // 打开控制台,失败则结束程序

          if ( (console_fd = open("/dev/console" , O_WRONLY) )== -1)

          {

               fprintf(stderr, "Failed to open console. \n") ;

               perror("open") ;

               exit(1) ;

          }

          // 真正开始让扬声器发声

for (i = 0; i < parms.reps; i++)

{

               // 数字1190000从何而来,不得而知

int magical_fairy_number = 1190000/parms.freq;

               ioctl(console_fd, KIOCSOUND, magical_fairy_number);  // 开始发声

               usleep(1000*parms.length);                           // 等待…

               ioctl(console_fd, KIOCSOUND, 0);                     // 停止发声

              usleep(1000*parms.delay);                            // 等待…

           }                                                      // 重复播放

              return EXIT_SUCCESS;

      }

2、Linux扬声器设备编程的应用

调试上面6.2 Linux扬声器编程的应用程序,实现扬声器唱歌。

3、U盘的使用

二、实习总结

Unit7  Linux并发程序设计

【实习要求】

1、掌握Linux进程控制

    包括:创建、运行、终止与同步

2、掌握Linux进程通信

    包括:管道的概念、模型与基本使用

3、掌握Linux命令接口管理进程的基本使用

    包括:ps、kill等

4、掌握Linux命令接口的重定向与管道的基本使用

    包括:重定向、管道等

【实习内容】

1、Linux进程控制

2、Linux进程通信

3、Linux命令接口管理进程

4、Linux命令接口的重定向与管道

7.1 Linux进程控制

在Linux中,进程是正在执行的程序。一个进程又可以开启另一个进程,被开启进程为子进程,开启者为父进程。因此Linux的进程环境提供了一个像文件系统目录树那样的层次结构。进程树的顶端是一个名为init的控制进程,该进程是所有用户进程的祖先。

Linux系统向程序员提供了一组进程控制方面的系统调用,其中最重要的有以下几个:

fork()系统调用,通过复制调用进程来建立新的进程,是最基本的进程建立操作。

exec系列系统调用,每个系统调用都完成相同的功能,即通过用一个新的程序覆盖调用者的内存空间,实现进程的转变。各种exec系统调用之间的区别仅在于它们的参数构造不同。

wait()系统调用,提供了初级的进程同步措施,能使一个进程等待,直到另一个进程结束为止。

exit()系统调用,终止一个进程的运行。

7.1.1 进程的创建

1、系统调用fork()

fork()的作用是创建一个新进程,它是调用进程的一个拷贝,除了它有自己的内存拷贝、自己的进程ID(具有与其他进程的正确关系)和自己的指向共享内核实体如文件描述符的指针。

在调用fork()之后,两个进程,父进程和子进程,将在它们各自的地址空间执行fork()的下一条语句。如果调用成功,那么在父进程中fork()返回新创建的子进程的进程ID,而在子进程中fork()返回零值。

原型:pid_t  fork();

说明:fork()在系统库unistd.h中声明,pid_t在系统库sys/types.h中声明。

示例:使用系统调用fork(),创建新进程。

#include <stdio.h>

#include <unistd.h>  

#include <sys/types.h>

main()

{

  pid_t pid;

  printf(“Now only one process\n”);

  printf(“Calling fork ...\n”);

  pid=fork();

  if (!pid)

    printf(“I’m the child\n”);

  else

    if (pid>0)

      printf(“I’m the parent,child has pid %d\n”,pid);

    else

      printf(“Fork fail!\n”);

}

2、系统调用getpid()

getpid()的作用是获得进程本身的进程标识符。

原型:pid_t getpid();

说明:getpid()在系统库unistd.h中声明。

示例:使用系统调用getpid(),获得进程标识符。

#include <stdio.h>

#include <unistd.h>

int main()

{

  printf("The current process ID is %d\n",getpid());  //输出本进程的ID

  return 0;

}

3、系统调用getppid()

getppid()的作用是获得当前进程的父进程标识符。

原型:pid_t getppid();

说明:getppid()在系统库unistd.h中声明。

示例:fork()创建子进程后,子进程在屏幕上显示子进程标识符与父进程标识符。

#include <stdio.h>

#include <unistd.h>  

main()

{

  pid_t  pid;

  printf(“Now only one process,PID is %d\n”);

  printf(“Calling fork ...\n”);

  pid=fork(); 

  if (!pid)

    printf("This is child process\n");

    printf("My PID(child) is %d\n",getpid());

    printf("My parent PID is %d\n",getppid());

  else

    if (pid>0)

      printf("This is parent process\n");

    else

      printf(“Fork fail!\n”);

}

7.1.2 进程的运行

fork()只能建立相同程序的副本。exec系列的系统调用,可以用于新程序的运行。exec系列中的系统调用都完成相同的功能,它们把一个新程序装入调用进程的内存空间,来改变调用进程的执行代码,从而形成新进程。如果exec调用成功,调用进程将被覆盖,然后从新程序的入口开始执行,这样就产生了一个新的进程,但是它的进程标识符与调用进程相同。

这就是说,exec没有建立一个与调用进程并发的新进程,而是用新进程取代了原来的进程。所以,在exec调用成功后,没有任何数据返回,这与fork()不同。

下面给出exec系列系统调用在Linux系统库中unistd.h中的函数声明:

int execl(const char *path, const char *arg, ...);

int execlp(const char *file, const char *agr, ...);

int execle(const char *path, const char *arg, ..., char * const envp[]);

int execv(const char *path, char * const argv[]);

int execvp(const char * file, char * const argv[]);

int execve(const char *path, char * const argv[], ..., char * const envp[]);

在这里我们着重讨论exec系列中的一个系统调用,即execl(),其余请读者通过Linux系统提供的man手册查阅并实验。

execl()调用的参数均为字符型指针,第一个参数path给出了被执行程序文件所在的有效路径名;第二个以及用省略号表示的其他参数一起组成了该程序执行时的参数表。参数表的第一项是不带路径的程序文件名,被调用的程序可以访问这个参数表,由于参数的个数是任意的,所以必须用一个NULL指针来标记参数表的结尾。注意,程序文件必须是一个真正的可执行程序,另外不能用execl()来运行一个shell命令组成的文件。

示例:使用execl()系统调用,运行目录列表程序ls

#include <stdio.h>

#include <unistd.h>

void main()

{

  printf("Executing is \n");

  execl("/bin/ls","ls","-l",NULL);

  perror("execl failed to run is");  //如果execl返回,说明调用失败

  exit(1);

}

示例:上述功能改用execv()系统调用完成。

#include <stdio.h>

#include <unistd.h>

void main()

{

  char * av[]={"ls","-l",NULL};

  printf("Executing is \n");

  execv("/bin/ls",av);

  perror("execv failed");

  exit(1);

}

示例:使用系统调用fork()exec,使父子进程运行完全不同的程序。

#include <stdio.h>

#include <unistd.h>

void main()

{

  int pid;

  pid = fork();

  switch (pid)

  {

    case -1:

      perror("fork failed");

      exit(1);

    case 0:

      execl("/bin/ls","ls","-l",NULL);

      perror("execl failed");

      exit(1);

    default:

      wait(NULL);

      printf("is completed\n");

      exit(0);

  }//switch (pid)

}

7.1.3 进程的终止

系统调用exit()

exit()的作用是实现进程的终止。

原型:void exit(int status);

说明:exit()在系统库stdlib.h中声明。

参数status称为进程的退出状态,父进程可以使用它的低8位。exit()的返回值通常用于指出进程所完成任务的成败。如果成功,则返回0;如果出错,则返回非0值。

exit除了停止进程的运行外,还有一些其他的作用,其中最重要的是,它可以关闭所有已打开的文件。如果父进程因执行了wait调用而处于睡眠状态,那么子进程执行exit会重新启动父进程运行。另外,exit还将完成一些系统内部的清除工作,例如缓冲区的清除等。

除了使用exit来终止进程外,当进程运行完程序到达main函数末时,进程会自动终止。当进程在main函数内执行return语句时,它也会终止。

在Linux中还有一个用于终止进程的系统调用_exit()。它在Linux系统函数库unistd.h中被声明:

void _exit(int status);

其使用方法与exit()完全相同,但是它只执行终止进程的动作而不对系统内部进行清除。因此,只有那些对系统内部了解比较深的程序员才使用它。

示例:使用系统调用exit(),终止进程。

#include <stdio.h>

#include <stdlib.h>

void main()

{

  printf("My PID is %d\n",getid());

  exit(0);

}

7.1.4 进程的同步

系统调用wait()

进程一旦调用了wait(),就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。

原型:pid_t  wait(int *status);

说明:wait()在系统库sys/wait.h中声明。

参数status:

参数status用来保存被收集的进程退出时的一些状态,它是一个指向int类型的指针。但如果对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,就可以设定这个参数为NULL,使用方法如下:

pid = wait(NULL);

如果成功,wait会返回被收集子进程的ID;如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD。

如果参数status的值不是NULL,wait就会把子进程退出时的状态取出并存入其中,这是一个整数值,指出了子进程是正常退出还是非正常结束的,以及正常结束时的返回值,或被哪一个信号结束的等信息。

由于这些信息存放在一个整数的不同二进制位中,所以用常规的方法读取会非常麻烦,人们就设计了一套专门的宏来完成这项工作,下面给出其中最常用的两个:

(1)WIFEXITED(status):这个宏用来指出子进程是否为正常退出的,如果是,它会返回一个非零值。

(2)EXITSTATUS(status):当WIFEXITED返回非零值时,可以用这个宏来提取子进程的返回值,如果子进程调用exit(5)退出,EXITSTATUS(status)就会返回5;如果子进程调用exit(7),EXITSTATUS(status)就会返回7。

注意:如果进程不是正常退出的,也就是说,WIFEXITED返回0,这个值就毫无意义。

示例:使用wait()系统调用,实现父子进程的简单同步。

#include <sys/types.h>

#include <sys/wait.h>

#include <unistd.h>

#include <stdlib.h>

main()

{

  pid_t pc,pr;

  pc=fork();        // 创建进程

  if (pc<0)         // 创建失败

  {

 printf("error ocurred!\n");

     exit(1);

}

  else

  {

  if (pc == 0)     // 子进程

    {

      printf("This i schild process with pid of %d\n",getpid());

      sleep(10);    // 睡眠10秒钟

    }

    else           // 父进程

    {

      pr=wait(NULL);    // 在这里等待

      printf("I catched a child process with pid of %d\n",pr);

    }

  exit(0);       // 结束父进程

}

}//main

7.1.5 进程挂起

系统调用sleep()

sleep()使进程挂起指定的秒数。

原型:unsigned int sleep(unsigned int seconds);

说明:sleep()在系统库unistd.h中声明。

该函数调用使得进程挂起一个指定的时间,直到指定时间用完或者收到信号。如果指定挂起的时间到了,该调用返回0;如果该函数调用被信号打断,则返回剩余挂起的时间数,即指定的时间减去已经挂起的时间。

示例:让子进程睡眠1分钟。

#include <unistd.h>

#include <stdlib.h>

main()

{

  pid_t pc,pr;

  pc=fork();        // 创建进程

  if (pc<0)         // 创建失败

   {

 printf("error ocurred!\n");

     exit(1);

}

  else

   {

 if (pc == 0)     // 子进程

    {

      printf("This is child process with pid of %d,enter sleep...\n",getpid());

      sleep(60);    // 睡眠60秒钟

      printf("sleep is over!\n");

    }

    else           // 父进程

    {

      printf("This is parent process with pid of %d,wait child...\n",getpid());

      pr=wait(NULL);    // 在这里等待

      printf("I catched a child process with pid of %d\n",pr);

    }

  exit(0);       // 结束父进程

  }

}//main

7.2 Linux进程通信

1、管道

管道,简单地说就是连接一个程序的输出和另一个程序的输入的单向通道。在UNIX/Linux系统的各种进程通信方法中,它是最古老而应用最为广泛的一种,特别是在shell中,如:

#ls -l|more

2、管道在Linux系统中的模型

当进程创建一个管道的时候,系统内核同时为该进程设立了一对文件句柄,一个用来从该管道获取数据(read),另一个则用来做向管道的输出(write)。

图7-1显示了进程和管道间的相互作用。图中可以清楚地看出进程和管道是如何通过句柄进行数据交换的。进程通过句柄fd[0]向管道写入(write)数据,同时通过fd[1]从管道读出(read)数据。理解了这一点,我们就可以容易地掌握管道I/O处理了。

图7-1 进程和管理间的相互作用

在主进程中利用fork()函数创建一个自身的自进程。fork()的子进程自动继承了父进程打开的文件句柄。利用继承的句柄,就可以实现父/子间的通信了。这个关系可以用图7-2来表示。

图7-2 fork()函数调用后的管道

现在,父子两个进程同时拥有对同一个管道的读写句柄。管道必须是单向的,因为它没有提供锁定的保护机制,所以我们必须决定数据的流动方向,即是从父到子,还是从子到父?然后在每个进程中关闭不需要的句柄。假设需要管道从子进程向父进程传送数据,那么关闭相应句柄后的管道可以用图7-3来表示。

图7-3 关闭了相应句柄后的管道

这样,一个完整的管道就被建立了。下面我们就可以使用read()和write()等系统调用来对管道进行读写操作了。

3、管道的使用

(1)系统调用pipe()

pipe()的作用是用来建立管道。

原型:int pipe(int fd[2]);

参数:一个只有两个整型元素的数组,用于存放pipe()函数新建立的管道句柄。fd[0]用来从管道中读,fd[1]用来向管道中写,即fd[1]的写入由fd[0]读出。

返回:返回值为0,成功;

      返回-1,出错,EMFILE(no free descriptors)无空余句柄;

                    EMFILE(system file table is full)系统文件分配表满;

                    EFAULT(fd array is not valid)fd数组非法。

管道建立后,我们使用fork()建立一个子进程,然后,假设需要管道中数据的流动是从子进程到父进程。这样父进程就需要关闭(close())写管道的句柄(fd[1]),而子进程需要关闭读管道的进程(fd[0])。管道建立之后,我们就可以操作管道了。

示例:在父子进程间建立管道,且子进程向父进程输送信息。

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

int main(void)

{

  int fd[2],nbytes;

  pid_t childpid;

  char string[]="Hello,world!\n";

  char readbuffer[80];

  pipe(fd);

  if ((childpid=fork())==-1)

  {

    perror("fork");

    exit(1);

  }

  if (childpid==0)

  {

    //子进程关闭管道的读句柄

    close(fd[0]);

    //通过写句柄向管道写入信息

    write(fd[1],string,strlen(string));

    _exit(0);

  }

  else

  {

    //父进程关闭管道的写句柄

    close(fd[1]);

    //通过读句柄从管道读出信息

    nbytes = read(fd[0],readbuffer,sizeof(readbuffer));

    printf("Received string:%s",readbuffer);

  }

  return(0);

}

(2)dup()/dup2()系统调用

dup()/dup2()的作用是将管道句柄定向到标准I/O(stdin/stdout)上去。

原型:int dup(int oldfd);

返回:new descriptor on success

      -1 on error:

errno=EBADF(Oldfd is not a valid descriptor)oldfd不是合法的句柄

      EBADF(newfd is out of range)新句柄超界

      EMFILE(too many descriptors for the process)进程可使用的句柄数已满

注意:旧句柄没有被关闭,新旧两个句柄可以互换使用。

虽然原句柄和新句柄是可以互换使用的,但为了避免混淆,通常会将原句柄关闭(close)。同时要注意,在dup()函数中无法指定重定向的新句柄,系统将自动使用未被使用的最小文件句柄(记住,句柄是一个整型量)作为重定向的新句柄。

示例:dup的使用方法。

......

pipe(fd);

childpid=fork();

if (childpid==0)

{

  //关闭子进程的文件句柄0(stdin)

  close(0);

  //将管道的读句柄定义到stdin

  dup(fd[0]);

  execlp("sort","sort",NULL);

  ......

}

例子中巧妙地利用了dup()函数的特性。因为文件句柄0(stdin)被关闭了,对dup函数的调用将管道读句柄fd[0]定向到了stdin(因为句柄0是最小的未用句柄)。然后调用execlp函数,用外部过程sort覆盖子进程的代码。因为它继承了子进程的基本输入/输出,所以它将管道作为它的输入。现在,我们在父进程里向管道写入的任何数据都将自动被sort接受进行排序。

在Linux系统中还有一个系统函数dup2()。单从函数名上也可以判断出它和dup()函数的渊源。

原型:int dup2(int oldfd,int newfd);

返回:new descriptor on success

      -1 on error:

errno=EBADF(Oldfd is not a valid descriptor)oldfd不是合法的句柄

      EBADF(newfd is out of range)新句柄超界

      EMFILE(too many descriptors for the process)进程可使用的句柄数已满

注意:旧句柄将被dup2()自动关闭。

显然,原来的close以及dup是一套调用现在全部由dup2()来完成。这样不仅简化了程序,更重要的是,保证了操作的独立性和完整性,使操作不会被外来的信号所中断。在原来的dup()调用中,必须先调用close()函数。假设此时恰好有一个信号使接下来的dup()调用不能立即执行,这就会引发错误(进程没有了stdin)。使用dup2()就不会有这样的危险。

示例:dup2()使用方法。

......

pipe(fd);

childpid=fork();

if (childpid==0)

{

  //将管道的读入端定向到stdin

  dup2(0,fd[0]);

  execlp("sort","stor",NULL);

  ......

}

7.3 Linux重定向和管道

7.4 管理Linux系统进程

7.5 思考题

1、fork()创建子进程后,子进程在屏幕上显示:This is child process、My PID(child) is CCC、My parent PID is PPP,父进程在屏幕上显示:This is parent process、My PID(parent) is PPP、My child PID is CCC。其中PPP为父进程标识符,CCC为子进程标识符。

2、请证明下面程序中父子进程是完全不同的两个进程,即父进程未被子进程覆盖。

#include <stdio.h>

#include <unistd.h>

void main()

{

  int pid;

  pid = fork();

  switch (pid)

  {

    case -1:

      perror("fork failed");

      exit(1);

    case 0:

      execl("/bin/ls","ls","-l",NULL);

      perror("execl failed");

      exit(1);

    default:

      wait(NULL);

      printf("is completed\n");

      exit(0);

  }//switch (pid)

}

3(*)、使用fork()系统调用创建子进程,用wait()系统调用阻塞父进程,直到子进程结束后再唤醒父进程,要求父进程获取子进程的结束状态。

4(*)、列举在管道使用中需要注意的问题。

5、Linux中,提供了输入/输出重定向和管道命令

(1)重定向运算符有哪些,各自的作用是什么?

(2)管道运算符是什么,其作用是什么?

(3)采用管道和重定向组合的方法统计出目录/etc下的文件个数后存入文件count中。

(4)将命令ls、passwd的帮助信息依次存入文件manls。

【实习报告】

实习报告:Linux并发程序设计

学生姓名:       班级:        学号:

一、实习内容

1、Linux进程控制

调试上面7.1 Linux进程控制的各程序代码。

2、Linux进程通信

  调试上面7.2 Linux进程通信的各程序代码。

并完成并发程序设计的实验内容:

并发程序的设计关键是使用创建进程的系统调用,使一个程序运行时可以生成几个同时运行的程序,如果程序中没有创建进程的动作则为顺序程序设计。

本实验中的并发程序例子完成两个程序child和father之间的数据传递工作,具体做法分为四步。

步骤1编制并发程序pipeline.c。

单击红帽子,在“GNOME帮助”菜单中单击“附件”-“文本编辑器”命令,在文本编辑中键入程序并保存为pipeline.c。

在该程序中定义管道和文件描述符,并且创建子进程child。该程序用到的系统调用有pipe() 、dup() 、fork() 、close、execl() 、exit,它们的功能分别是建立管道、复制文件描述符、创建进程并使子进程与父进程有相同的程序正文、关闭文件描述符、用指定文件覆盖调用程序、撤销当前进程。

    清单4-5 pipeline.c

// 定义管道程序

# define STD_INPUT 0                                  // 定义标准输入设备描述符

# define STD_OUTPUT 1                              // 定义标准输出设备描述符

int fd[2];

main()

{

static char process1[]="father",process2[]="child";

               pipe(fd);                                                 // 定义管道

               pipeline(process1,process2);                  // 调用自定义函数pipeline()

               exit(1);                                                   // 程序结束

}

pipeline(char* process1,char* process2)

{

          int i;

               while ((i=fork())==-1);                          // 创建进程,直到创建成功为止

          if (i)

               {

                         close(fd[0]);                                  // 关闭管道输入描述符

                         close(STD_OUTPUT);                // 关闭标准输出描述符1

                         dup(fd[1]);                                    // 指定标准输出描述符1为管道写指针

                         close(fd[1]);                                  // 关闭原始管道写指针

execl(process1, process1, 0);        // 用程序father覆盖当前程序

                         printf(" father failed.\n");              // execl()执行失败

               }

               else

               {

                         close(fd[1]);                                  // 关闭管道输出描述符

                         close(STD_INPUT);                    // 关闭标准输入描述符0

                         dup(fd[0]);                                    // 指定标准输入描述符0为管道读指针

                         close(fd[0]);                                  // 关闭原始管道读指针

                         execl(process2,process2,0); // 用程序child覆盖当前程序

                         printf("child failed.\n");                // execl()执行失败

               }

               exit(2);                                                   // 程序结束

}

步骤2编制“管道写”程序father.c作为父进程的一部分工作。其内容如下:

单击红帽子,在“GNOME帮助”菜单中单击“附件”-“文本编辑器”命令,在文本编辑中键入程序并保存为father.c。

    清单4-6  father.c

 main()

      {

          static char string[] = “Parent is using pipe write.” ;

          int len;

          len = sizeof(string) ;

          write(l, string, len) ;                       /* 将string中的内容写入管道中 */

          printf(“parent, parent, parent \n \n \n” ) ;

          exit(0) ;

      }

步骤3编制“管道读”程序child.c作为子进程的一部分工作。其内容如下:

单击红帽子,在“GNOME帮助”菜单中单击“附件”-“文本编辑器”命令,在文本编辑中键入程序并保存为child.c。

    清单4-7  child.c

     main()

      {

          char output[30] ;

          read (0, output, 30) ;                      /* 从管道中读数据并存入output中 */

          printf(“%s \n child, child. \n” , output) ;

          return(0) ;

      }

步骤4编译。

cc –o child  child.c

cc -o father  father.c

cc -o pipeline  pipeline.c

步骤5运行。

./pipeline

若运行不成功,则应该用文本编辑器对源程序进行修改调试。

运行显示结果为:

    ____________________________________________________________________

________________________________________________________________________

________________________________________________________________________

3、Linux命令接口管理进程

步骤1:登录进入GNOME。

在Linux登录框中填写指导老师分配的用户名和口令,登录Linux系统。

步骤2:访问命令行。

单击红帽子,在“GNOME帮助”菜单中单击“系统工具”-“终端”命令,打开“终端”窗口。

步骤3:回顾系统进程概念。

每个运行的程序都会创建一个进程,进程分配到一个唯一的进程标识符 (PID) 。PID被系统用于标识和跟踪进程,直到进程结束。操作系统内核管理所有进程的初始化和终止。每一个进程都要求系统资源 (例如CPU时间和RAM空间) 在其中工作。当进程启动的时候,操作系统把系统资源分配给每个进程,当进程终止的时候,系统回收这些资源。在Linux系统启动的时候,首先启动的两个进程是sched (调度) 和init (初始化) ,它们管理着其他进程。Linux系统中有几种不同类型的进程:

守护进程:由Linux内核启动的进程,为了特定目的而存在。例如,lpsched守护进程存在只是为了处理打印作业。

父进程:派生其他进程的进程是父进程。一个叫做init的守护进程是第一个调用的进程。每一个进程,除了init之外,都有一个父进程。

子进程:由其他进程派生出来的进程叫做子进程。

孤儿进程:在进程返回输出之前,它的父进程结束了,这样的进程叫做孤儿进程。

僵进程:子进程没有带着输出返回给父进程。这样的进程在系统中变成丢失的进程。

使用此前的信息,完成以下填空:

1) Linux系统中,几乎每一个启动的进程,都会由内核分配一个唯一的_______________进程标识符,用于跟踪从进程启动到进程结束。

2) 当启动新进程的时候,内核也给它们分配系统资源,如________和________。

3) 永远不向父进程返回输出的进程叫做______________。

4) 由父进程派生出来的进程叫做__________________进程。

5) ________________进程是一个派生另一个进程的进程。

6) 运行用于提供服务的Linux系统进程是_______________。

7) 如果父进程在子进程之前结束,它创建了一个______________进程。

步骤4:回顾ps命令和信息。

ps命令用于列出当前系统中运行的进程。

如果一个进程耗时太长,或者看上去好像已经终止了,表现为一个终端窗口不再响应或挂起,通常需要使用ps查看系统中的进程。通过列出进程,可以查看初始化进程的命令或程序的名字,以及所有它派生出来的子进程。通过多次执行ps命令,查看进程的时间——进程占用的CPU时间,可以检查一个进程是否还在运行。如果时间小再增长,那么进程可能已经终止了。如果进程占用太长的时间或者已经停止,可以使用ps命令检查进程的进程ID (PID) ,然后杀死进程。

ps命令的输出将显示PID号和与其相关的命令或程序。PID号通常用于终止一个进程。ps命令 ( ps [-options] ) 的3个主要选项如下表所示。

表3-5  ps命令选项

ps选项

意义

功能

Ps

无选项

显示当前shell或终端窗口中,当前用户的进程信息

ps –e

每一个

显示系统中每一个进程的信息

ps –f

完全

产生一个完全列表,给出每个进程的所有可用信息

ps -u userid

用户

显示特定用户的所有进程

基本的ps命令显示在当前shell中的进程信息,用户只能够查看在这个终端窗口中初始化的进程。输入ps命令,将结果填入表3-6中。

表3-6  实验记录

PID

TTY

TIME

CMD

从当前终端窗口中,练习使用给出的每个选项的ps命令。

输入 ps -f 命令,显示运行在系统中的某个进程的完全信息,填入表3-7中。

表3-7  实验记录

UID

PID

PPID

C

STIME

TTY

TIME

CMD

ps -f命令输出的各栏标题见表3-8所示。

表3-8  ps -f栏标题

描述

UID

初始化进程的用户ID

PID

进程的进程标识号。PID可以用来杀死进程

PPID

  进程的父进程标识号

C

  进程的优先级

STIME

进程的启动时间

TTY

控制进程终端的终端举型

TIME

进程使用的CPU时间的数量

CMD

命令名守护进程 (执行的程序的名字)

步骤5:列出系统中运行的所有进程。

输入 ps -ef 命令,显示运行在系统中的各个进程的完全信息。执行该命令,并与ps –f命令的输出结果对照,一致吗?有何不同?

____________________________________________________________________

________________________________________________________________________

注意分析当前终端窗口中的输出结果:

a. 显示了多少个进程?

____________________________________________________________________

b. 进程ID的PID是什么?

____________________________________________________________________

c. 启动进程的命令 (CMD) 是什么?

____________________________________________________________________

d. 请观察,什么命令的PID号是1?

____________________________________________________________________

e. 再次运行ps –ef命令,计算进程的数目:

____________________________________________________________________

然后执行下列命令把输出结果输入到wc命令中:

              ps -ef | wc -l

第一个数字显示的是行的数目,也是进程的数目:

____________________________________________________________________

执行 man ps命令,可以打开Linux用户命令手册,了解ps命令的用法,输入wq命令可退出用户手册的阅读。man命令可以执行吗?结果如何?

____________________________________________________________________

步骤6:根据命令名搜索特定的进程。

为了终止一个进程,必须找到该进程的PID。大多数运行的系统中,有上百个进程在运行,ps -ef的列表可能很长。如果知道启动进程的执行程序的名字,可以更快地找到PID。

通过把ps命令的输出结果输入到grep中,可以搜索想要终止的特定进程,确定正确的PID。

grep命令可以在其他命令的输出中搜索所有类型的特征字符串。-l (长的输出) 选项将显示和找到的PID相关的进程的名字;-e选项显示PID和初始化命令的名字。

a. 单击红帽子,在“GNOME帮助”菜单中单击“游戏”-“堆麻将”命令,打开“堆麻将”游戏。

b. 在当前的终端窗口中,执行命令:

ps –e | grep mahjongg

 (“堆麻将”游戏的进程名是“mahjongg”) ,查找和“堆麻将”游戏调度守护进程相关的所有进程。

c. 显示了多少个相关进程?

____________________________________________________________________

d. 显示进程中最小的进程ID号是多少?

       ____________________________________________________________________

c. 在当前终端窗口中执行命令:

pgrep –l mahjongg

查找所有和“堆麻将”游戏调度守护进程相关的进程。ps和pgrep命令输出之间有什么不同?

       ____________________________________________________________________

步骤7:确定一个要终止的进程。

当试图终止一个程序,或者释放一个挂起的终端窗口的时候,杀死和不响应的应用相关的PID可能还是不够的,一般需要杀死那个进程的父进程,在少数情况下,甚至要杀死父进程的父进程。为了沿着层次结构,从子进程追溯到派生它们的父进程,必须能够查找PID和PPID。

必须首先确定最低级不响应进程的PID。通常,可以试着去杀死那个进程。如果这样做不能够停止那个进程,可能需要杀死它的父进程。杀死父进程将杀死所有它派生的子进程。杀死一个父进程也比杀死几个子进程快得多。

1) 在GNOME当前终端窗口中,输入ps命令。

有多少进程正在运行?为什么只有这么少的进程?

       ____________________________________________________________________

2) 正在运行的进程的名字是什么?它表示什么?

       ____________________________________________________________________

3) 这个进程的PID是多少?

       ____________________________________________________________________

4) 在bash shell中输入命令csh,打开一个C shell会话,当前系统的会话提示符是什么?

       ____________________________________________________________________

5) 输入 ps -f 命令,显示在当前shell中运行的进程的所有信息。现在什么进程正在运行?

       ____________________________________________________________________

6) bash的PID是-sh (csh) 的PPID吗?

       ____________________________________________________________________

7) 输入命令sleep l000&,创建一个进程,把执行挂起1000秒 (大约15分钟) 。&表示在后台运行命令,返回shell提示符,这样您可以继续工作。

8) 再次输入ps -f命令。-sh (csh) 的PID是sleep命令的PPID吗?哪个PID是csh (C shell) 的子进程?

       ____________________________________________________________________

________________________________________________________________________

9) 输入命令 kill -9 <csh的PID> 退出C shell。然后再次键入ps -f命令。什么PID是sleep父命令的PPID?

       ____________________________________________________________________

sleep进程现在是什么类型的进程?

       ____________________________________________________________________

步骤8:使用kill命令终止一个进程。

信号用于终止、挂起和继续进程。有时候使用Ctrl + c可以终止一个不响应的进程。这样向进程发送一个中断 (INT) 信号,终止它及所有它派生的子进程。

kill命令提供了一个终止不想要的命令进程的直接方法。当想停止一个运行了很长时间的命令的时候,或者当需要终止一个不能够正常退出的进程的时候,它很有用。指定PID正常地杀死一个进程。

  kill [-signal] process -id

为了使用kill命令终止一个进程,应该首先键入ps找出进程的PID,然后键入kill紧跟着PID。如果使用kill而没有指定信号,则信号15 (SIGTERM) 将被发送给特定PID号的进程。这叫做软杀死,通常终止了进程。如果可能,最好软杀死进程,这样它可以正确地关闭文件,温和地终止进程。

如果需要强制终止一个进程,可以使用带 -9选项的kill命令。这个选项叫做强制杀死,当shell对所有其他终止信号都不响应的时候,需要使用它来杀死shell。

  kill -9 process -id

注意:对于shell之外的进程,把kill –9 (SIGKILL) 作为最后的选项,因为它是一种生硬的方法,不允许正确的进程终止。

a. 输入命令ps –f ,显示在当前shell中运行的进程的完整信息。现在什么进程正在运行?

       ____________________________________________________________________

b. 因为sleep进程现在是一个孤儿进程,已经被init进程 (PID #l) 收养,输入命令,对sleep的PID执行软杀死。如果sleep已经终止 (超过15分钟) ,则重复步骤7中的8) 、9) 操作,然后软杀死sleep程序。再次输入ps -f命令。现在什么进程正在运行?

       ____________________________________________________________________

步骤9:按照用户查找和终止一个进程。

ps命令可以带 -u (用户) 选项使用,查找指定用户的进程。这个命令比ps-ef使用得更多,因为一般只能够管理属于自己的进程。我们可以通过用户登录名或者UID号来查找用户的进程。用户只能够终止自己的进程,但是超级用户可以终止系统中所有运行的进程。

      ps –u login-ID或UID

1) 启动计算器和“堆麻将”游戏GNOME应用程序。

2) 使用带 -u选项的ps命令,查找以登录ID (例如,userX) 或者数字UID (例如,1004) 运行的所有进程。计算器应用程序的PID是什么?

       ____________________________________________________________________

3) 使用软杀死终止计算器应用程序,“堆麻将”是否仍然在桌面上运行?

    ____________________________________________________________________

4) 使用ps -u命令组合grep,查找“堆麻将”程序的PID号,而不是使用ps -u查找整个列表。您使用什么命令?

提示:猜猜“堆麻将”程序的命令名中可能有哪个字母,使用grep搜索那些字母。

       ____________________________________________________________________

5) 终止“堆麻将”程序。它是否还在桌面上运行?

     ____________________________________________________________________

6) 退出 C shell。

步骤10:删除所有在本实验中创建的文件和目录。

4、Linux命令接口的重定向与管道

1. 使用重定向标准输出符号

步骤3:重定向标准输出,创建一个文件。

右尖括号或称大于符号 (>) 把命令的输出发送到一个文件中:使用单个右尖括号,当指定文件名不存在的时候,将创建一个新文件;如果文件名存在,它将被覆盖。(注意:命令、重定向符号和文件名之间的空格是可选的) 。

重定向标准输出命令的格式是:

      command > file

1) 为核实当前所在目录位置,使用什么命令?

    ____________________________________________________________________

如果当前位置不在主目录中,使用什么命令可以改变到主目录中?

    ____________________________________________________________________

2) 如果希望把文件和目录列表截获,存储为主目录中的一个文件,这样可以追踪主目录中有什么文件。使用什么命令,把长文件列表的输出重定向,创建一个叫做homedir.list的文件。

    ____________________________________________________________________

3) 新文件homedir.list被放在哪里?

    ____________________________________________________________________

使用ls命令核实新文件存在。

4) 使用什么命令,以一次一屏的方式,来查看刚才创建的文件内容?

    ____________________________________________________________________

5) 使用head命令截获homedir.list文件的前10行,通过重定向,创建一个叫做dhomedir.list-top-10的新文件。应该使用什么命令?

    ____________________________________________________________________

使用more命令查看文件的内容。

6) 使用tail命令,截获homedir.list文件的最后10行,通过重定向,创建一个叫做dhomedir.list-top-10的新文件。使用什么命令?

    ____________________________________________________________________

使用more命令查看文件的内容。

7) 截获cal -y命令的输出,把它存到名为calendar的文件中。查看文件的内容。截获了什么?

    ____________________________________________________________________

8) 截获cal 2010命令的输出,把它存到名为calendar的文件中。查看文件的内容。其中有什么内容?

    ____________________________________________________________________

日历有什么变化?

    ____________________________________________________________________

步骤4:防止使用重定向的时候覆盖文件。

在bash shell中,一个叫做noclobber的选项可以用来设定防止在重定向的过程中覆盖文件。可以在命令行中使用$set -o noclobber命令来完成。o代表选项。

为了重新激活clobber特性,使用$set -o noclobber;撤消则用set +o noclobber。

如果你使用的是csh shell,为了激活/撤消C shell中的clobber特性,使用set noclobber和unset noclobber。

1) 输入命令,打开shell中的noclobber选项。输入什么命令?

    ____________________________________________________________________

2) 输入命令ls -l > homedir.list,结果是什么?

    ____________________________________________________________________

3) 输入命令ls -l > homedir.list2,结果是什么?

    ____________________________________________________________________

步骤5:向现有的文件追加输出。

如果想向一个现有的文件追加 (添加到末尾) 文本而不是覆盖它,可以使用双右尖括号 (>>) 。这个选项当文件不存在的时候,会创建一个新文件,或者追加到已有文件。

追加命令的格式是:

      command >> file

1) 输入命令,显示“Happy Bday”一行字,使用重定向符号截获输出,把它存到叫做bday4me的文件中。使用什么命令?

    ____________________________________________________________________

2) 输入命令,显示“YOURNAME!”一行字,使用双重定向符号,把输出追加到bday4me文件中。查看bday4me文件的内容。其中有什么?

    ____________________________________________________________________

3) 输入命令,显示您出生年月的日历 (如果在1985年的6月出生,输入cal 6 1985) ,使用双重定向符号,把输出追加到bday4me文件中。使用什么命令?

    ____________________________________________________________________

4) 查看bday4me文件的内容。注意这3个命令的输出在bday4me文件中已经被组合起来了。您是在一周中的哪一天出生的?

____________________________________________________________________

2. 使用管道符号

步骤6:把命令的输出导入到另一个命令中。

1) 使用管道元字符,发送ls -l命令的输出,作为more命令的输入 (注意:如果在当前目录中没有太多的文件,使用 /etc目录获取长列表) 。把输出作为more命令的输入的时候,得到什么结果?

    ____________________________________________________________________

2) 查看使用ls –l | more命令列出来的文件,注意创建或修改的日期。为了查看在同一个月被创建或修改的文件或目录的列表,可以使用grep命令对那个月进行搜索。当月份显示在列表中的时候,指定它 (例如:Oct) 。输入命令ls -1 | grep Oct (或者想查找的月份) 。结果是什么?

    ____________________________________________________________________

3) 目录总是4096字节大小。输入命令ls -1 | grep 4096。产生的列表是什么?

    ____________________________________________________________________

________________________________________________________________________

4) 可以使用多个管道连接多个命令。输入取得长文件列表输出的命令,把它输入给tail命令,然后到sort命令。输入的命令是:

    ____________________________________________________________________

5) ps (进程状态) 命令用于查看Linux系统中运行什么进程。把ps -e命令的输出输入给more命令。-e选项将给出每一个在系统中运行的进程。把输出输入到more命令中的结果是什么?

    ____________________________________________________________________

步骤7:删除在本实验中创建的文件和目录。

步骤8:关闭终端窗口,注销。

可选练习

1. 使用set -o命令不指定任何选项,可以查看noclobber特性是否已经打开。

1) 输入set -o。noclobber特性打开还是关闭的?如果它是关闭的,打开它。使用什么命令?

    ____________________________________________________________________

2) 永久的关闭noclobber特性。使用什么命令?

    ____________________________________________________________________

2. 可以把管道和重定向组合起来使用,达到特殊的效果。输入命令创建一个名为top5.list的文件,内容为主目录中的头5行记录,使用什么命令?

    ____________________________________________________________________

二、实习总结

 

【实习报告】

实习报告  综合应用

学生姓名:       班级:        学号:

一、实习内容

1、设计并实现Linux进程并发的应用程序――音画同步

要求:

(1)至少两个进程并发,一个子进程为扬声器唱歌,父进程为动画进程。

(2)进程同步与通信,子进程每唱一句,父进程动态显示歌词(或情景画面)。

2(*)、自行设计一个应用主题,需多于两个进程的并发

二、实习总结

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值