linux

 

 

Linux操作系统

 

Linux 与Unix的关系

Linux是当前流行的一种操作系统,是Unix的一个变种。它虽然从操场作及结构上看起来非常像Unix,但它的所有代码都有是重新编写的。这一切我们得感谢芬兰人Linus Toralds。Linux包含了Unix的全部功能和特性。

 

Linux特点

Linux操作系统在短短的几年之内得到了非常迅猛的发展,这与Linux具有的良好特性是分不开的。Linux包含了Unix的全部功能和特性。简单的说,Linux具有以下主要特性:http://202.205.177.137/zyypx/jsjj/computer_center/linux/tedian.htm

  1. 开放性
    开放性是指系统遵循世界标准规范,特别是遵循开放系统互连(OSI)国际标准。凡遵循国际标准所开发的硬件和软件,都能彼此兼容,可方便地实现互连。

     

  2. 多用户
    多用户是指系统资源可以被不同用户各自拥有使用,即每个用户对自己的资源(例如:文件、设备)有特定的权限,互不影响。 Linux和Unix都具有多用户的特性。  

     

  3.  多任务
    多任务是现代计算机的最主要的一个特点。它是指计算机同时执行多个程序,而且各个程序的运行互相独立。 Linux系统调度每一个进程平等地访问微处理器。由于CPU的处理速度非常快,其结果是,启动的应用程序看起来好像在并行运行。事实上,从处理器执行一个应用程序中的一组指令到Linux调度微处理器再次运行这个程序之间只有很短的时间延迟,用户是感觉不出来的。

     

  4. 良好的用户界面
    Linux向用户提供了两种界面:用户界面和系统调用。Linux的传统用户界面是基于文本的命令行界面,即shell,它既可以联机使用,又可存在文件上脱机使用。shell有很强的程序设计能力,用户可方便地用它编制程序,从而为用户扩充系统功能提供了更高级的手段。可编程Shell是指将多条命令组合在一起,形成一个Shell程序,这个程序可以单独运行,也可以与其他程序同时运行。系统调用给用户提供编程时使用的界面。用户可以在编程时直接使用系统提供的系统调用命令。系统通过这个界面为用户程序提供低级、高效率的服务。Linux还为用户提供了图形用户界面。它利用鼠标、菜单、窗口、滚动条等设施,给用户呈现一个直观、易操作、交互性强的友好的图形化界面。

     

  5. 设备独立性
    设备独立性是指操作系统把所有外部设备统一当作成文件来看待,只要安装它们的驱动程序,任何用户都可以象使用文件一样,操纵、使用这些设备,而不必知道它们的具体存在形式。具有设备独立性的操作系统,通过把每一个外围设备看作一个独立文件来简化增加新设备的工作。当需要增加新设备时、系统管理员就在内核中增加必要的连接。这种连接(也称作设备驱动程序)保证每次调用设备提供服务时,内核以相同的方式来处理它们。当新的及更好的外设被开发并交付给用户时,操作允许在这些设备连接到内核后,就能不受限制地立即访问它们。设备独立性的关键在于内核的适应能力。其他操作系统只允许一定数量或一定种类的外部设备连接。而设备独立性的操作系统能够容纳任意种类及任意数量的设备,因为每一个设备都是通过其与内核的专用连接独立进行访问。Linux是具有设备独立性的操作系统,它的内核具有高度适应能力,随着更多的程序员加入Linux编程,会有更多硬件设备加入到各种Linux 内核和发行版本中。另外,由于用户可以免费得到Linux的内核源代码,因此,用户可以修改内核源代码,以便适应新增加的外部设备。

     

  6. 提供了丰富的网络功能
    完善的内置网络是Linux的一大特点。 Linux在通信和网络功能方面优于其他操作系统。其他操作系统不包含如此紧密地和内核结合在一起的连接网络的能力,也没有内置这些联网特性的灵活性。而Linux为用户提供了完善的、强大的网络功能。    支持Internet是其网络功能之一。Linux免费提供了大量支持Internet的软件,Internet是在Unix领域中建立并繁荣起来的,在这方面使用Linux是相当方便的,用户能用Linux与世界上的其他人通过Internet网络进行通信。文件传输是其网络功能之二。用户能通过一些Linux命令完成内部信息或文件的传输。远程访问是其网络功能之三。Linux不仅允许进行文件和程序的传输,它还为系统管理员和技术人员提供了访问其他系统的窗口。通过这种远程访问的功能,一位技术人员能够有效地为多个系统服务,即使那些系统位于相距很远的地方。

     

  7. 可靠的系统安全
    Linux采取了许多安全技术措施,包括对读、写进行权限控制、带保护的子系统、审计跟踪、核心授权等,这为网络多用户环境中的用户提供了必要的安全保障。

     

  8. 良好的可移植性
    可移植性是指将操作系统从一个平台转移到另一个平台使它仍然能按其自身的方式运行的能力。Linux是一种可移植的操作系统,能够在从微型计算机到大型计算机的任何环境中和任何平台上运行。可移植性为运行Linux的不同计算机平台与其他任何机器进行准确而有效的通信提供了手段,不需要另外增加特殊的和昂贵的通信接口。

     

 


Linux安装

 

硬件要求

  • CPU
    INTEL:386, 486, Celeron, Pentium, PII, PIII, PIV系列等

    AMD: K5, K6, K6-2, Athon 和 Duron等

    VIA Cyrix: 5x86,6x86,MII等

     

  • 内存
    Linux可以在很少的内存下使用权用,理论上最低限为4MB.通常只要主板能够去持,内存就能被Linux使用

     

  • 硬盘
    Linux去持几乎所有的MFM和IDE驱动器及大多数的RLL和ESDI驱动器。硬盘大小至少要有800M的

     

  • 光驱
    现在的大多为ATAPI弄的,能被LINUX直接支持。总之只要光驱品牌被支持,就没有问题

     

  • 显示系统
    Linux支持大部分的显示器和显示,但X Windows不支持部分显示设置,如果不能确定的话,可以从网上查找一下是否被支持。

     

  • 声卡
    正如显卡一样,主流声卡都会被支持。

     

  • 网络
    Linux支持的网络设备主要有网卡和调制解调器。网卡包括令牌网卡,FDDI光纤网卡,以太网卡等。

     

  • 鼠标
    支持的鼠标有多各,主要包括:串口鼠标,PS/2,MS COMPATIVE,LOGITECH等等。

     

 

安装步骤

在安装Red Hat Linux前要做的五件事情:确信有足够的文档可以在安装Red Hat Linux系统后使用确信有安装Red Hat Linux所需的部件确信您知道计算机的硬件配置和网络信息根据前两个任务决定安装Red Hat Linux的方式决定在硬盘的何处放Red Hat Linux,下面就将基本安装的过程简述一下:http://ibmur.hust.edu.cn/elearning/Linux/2-bottom.htm

  1. 光盘上引导系统
    从起动光盘上引导系统安装时,首先出现上面屏幕的信息。它提供若干起动选项如果你直接输入回车,将起动基于图形方式安装过程。这是一种最容易的安装方式。但是,如果你的显示卡不被支持或需要专门配置的话,例如在笔记本电脑系统中,可能就会出错。当使用图形方式安装出错时,安装程序就会起动文本的安装方式,使用文本和图形方式,过程是完全一样的

     

  2. 选择语言、键盘类型、鼠标类型

  3. 选择安装方式

  4. 创建分区,设置Lilo

  5. 配置网络

  6. 配置时区

  7. 配置用户和口令认证

  8. 选择安装包

  9. 配置X-Window

  10. 安装软件包

  11. 创建起动盘

 


Linux基本操作

 

Linux文件的复制、删除和移动命令

  1. cp命令
    该命令的功能是将给出的文件或目录拷贝到另一文件或目录中,同MSDOS下的copy命令一样,功能十分强大。

    用法:cp [-f] [-i] [-p] f1 f2 cp [-f] [-i] [-p] f1 ... fn d1 cp -r|R [-f] [-i] [-p] d1 ... dn-1 dn

     

  2. mv命令
    用户可以使用mv命令来为文件或目录改名或将文件由一个目录移入另一个目录中。该命令如同MSDOS下的ren和move的组合。

    用法:mv [-f] [-i] f1 f2 mv [-f] [-i] f1 ... fn d1 mv [-f] [-i] d1 d2

     

  3. rm命令
    用户可以用rm命令删除不需要的文件。该命令的功能为删除一个目录中的一个或多个文件或目录,它也可以将某个目录及其下的所有文件及子目录均删除。对于链接文件,只是断开了链接,原文件保持不变

    用法::rm [-fiRr] 文件 ...

     

  4. mkdir命令
    说明:该命令创建由dir-name命名的目录。要求创建目录的用户在当前目录中(dir-name的父目录中)具有写权限,并且 dirname不能是当前目录中已有的目录或 文件名称

    用法:mkdir [-m 模式] [-p] dirname ...

     

  5. cd 命令
    说明:该命令将当前目录改变至directory所指定的目录。若没有指定directory, 则回到用户的主目录。为了改变到指定目录,用户必须拥有对指定目录的执行和读 权限。

     

  6. pwd 命令
    说明:此命令显示出当前工作目录的绝对路径。

     

  7. ls 命令
    对于每个目录,该命令将列出其中的所有子目录与文件。对于每个文件,ls将输出 其文件名以及所要求的其他信息。默认情况下,输出条目按字母顺序排序。当未给出目录名或是文件名时,就显示当前目录的信息。

    用法:ls -1RaAdCxmnlogrtucpFbqisfL [文件]

     

 

Linux文本处理命令

  1. sort命令
    说明:sort命令对指定文件中所有的行进行排序,并将结果显示在标准输出上。如不指定输入文件或使用“- ”,则表示排序内容来自标准输入。

    用法:sort [-cmu] [-o 输出] [-T 目录] [-S mem] [-z recsz] [-dfiMnr] [-b] [-t char] [-k keydef] [+pos1 [-pos2]] 文件...

     

  2. uniq命令
    说明:这个命令读取输入文件,并比较相邻的行。在正常情况下,第二个及以后更多个重复行将被删去,行比较是根据所用字符集的排序序列进行的。该命令加工后的结果写到输出文件中。输入文件和输出文件必须不同。如果输入文件用“- ”表示,则从标准输入读取

    Usage: uniq [-c|-d|-u][-f fields][-s char] [input_file [output_file]]

     

  3. tar命令
    利用tar命令,可以把一大堆的文件和目录全部打包成一个文件,这对于备份文件或将几个文件组合成为一个文件以便于网络传输是非常有用的。

    用法:tar {txruc}[vfbFXhiBEelmopwnq[0-7]] [-k 大小] [磁带文件] [块大小] [exclude-file] [-I include-file] 文件 ...

     

  4. gzip命令
    gzip是在Linux系统中经常使用的一个对文件进行压缩和解压缩的命令

    usage: gzip [-cdfhlLnNrtvV19] [-S suffix] [file ...]

     

  5. unzip命令
    可以用unzip命令,该命令用于解扩展名为.zip的压缩文件。

    Usage: unzip [-Z] [-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]

     

  6. chmod 命令
    用于改变文件或目录的访问权限。用户用它控制文件或目录的访问权限。

    用法: chmod [-fR] <绝对模式> 文件 ... chmod [-fR] <符号模式列表> 文件 ...

     

  7. chgrp命令
    说明:chown将指定文件的拥有者改为指定的用户或组。用户可以是用户名或用户ID。组可以是组名或组ID。文件是以空格分开的要改变权限的文件列表,支持通配符。

    用法:chgrp [-fhR] 组文件 ...

     

  8. 文件挂装 mount 命令
    mount 命令指示操作系统使文件系统在指定位置(安装点)可用。此外,可以用 mount 命令构建由目录和安装文件(file mounts) 组成的其他文件树。Mount 命令通过在 Directory 参数指定的目录上使用 Device/Node: Directory 参数来安装表示为设备的文件系统。mount 命令完成以后,指定的目录变为新安装文件系统的根目录。

    usage: mount [ -f ] [ -n Node ] [ -o Options ] [ -p ] [ -r ] [ -v VfsName ] [ -t Type | [ Device | Node:Directory ] Directory | all | -a ] [-V [generic_options] special_mount_points

    点击参见更详细的介绍http://www16.boulder.ibm.com/pseries/zh_CN/cmds/aixcmds3/mount.htm

    示例:在Linux环境下使用usb

    1. 步骤1
      在终端状态下输入如下命令:fdisk -l /dev/sda

      注意:不要在sda后面加通配符“*”或“?”,否则运行命令后返回的信息将不正常。如果您有多个USB设备话,则设备名在Linux下分别表示为sda、sdb、sdc等。  运行上面的命令后,电脑上返回如下图所示信息,表示系统已经找到笔者的USB设备,设备名称为/dev/sda1、可启动(Boot下面的那个*表示是活动分区),容量128MB、文件系统为FAT32。

       

    2. 步骤2
      在/mnt目录下建立一个挂装USB存储器的目录:mkdir /mnt/usb

       

    3. 步骤3
      然后再运行装载设备命令,将USB设备挂装到/mnt/usb目录下:mount -t msdos /dev/sda1 /mnt/usb 注意:如果在图2中显示您的USB设备的文件系统为FAT32,请使用mount -t vfat /dev/sda1 /mnt/usb命令装载USB设备。

       

    4. 步骤4
      运行如下命令即可查看USB存储器中的文件信息:ls /mnt/usb  然后您就可以像对待硬盘一样对USB存储器中的数据进行拷贝、删除等操作了。

       

 

Linux与用户有关的命令

  1. passwd命令
    还需使用passwd命令为每一位新增加的用户设置口令;用户以后还可以随时用passwd命令改变自己的口令。

     

  2. su命令
    它可以让一个普通用户拥有超级用户或其他用户的权限,也可以让超级用户以普通用户的身份做一些事情。普通用户使用这个命令时必须有超级用户或其他用户的口令.如要离开当前用户的身份,可以打exit。

    用法;su [选项] [? ] [使用者帐号]

     

  3. wall命令
    这个命令的功能是对全部已登录的用户发送信息,用户可以先把要发送的信息写好存入一个文件中,然后输入

     

  4. write命令
    write命令的功能是向系统中某一个用户发送信息。

    Usage: write user_name[终端]

     

  5. mesg指令
    mesg命令设定是否允许其他用户用write命令给自己发送信息。

    用法:mesg [-y | -n | y | n]

     

  6. free命令
    free命令的功能是查看当前系统内存的使用情况,它显示系统中剩余及已用的物理内存和交换内存,以及共享内存和被核心使用的缓冲区。

    USAGE: free [-b | -k | -m]

     

  7. uptime命令
    uptime命令显示系统已经运行了多长时间,它依次显示下列信息:现在时间、系统已经运行了多长时间、目前有多少登录用户、系统在过去的1分钟、5分钟和15分钟内的平均负载。

     

 

Linux磁盘管理命令

  1. df命令
    功能:检查文件系统的磁盘空间占用情况。可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息。

    用法: df [-F FSType] [-abegklntVv] [-o FSType-指定的_选项] [directory | block_device | resource]

     

  2. du命令
    du的英文原义为“disk usage”,含义为显示磁盘空间的使用情况

    用法:du [-a][-d][-k][-r][-o|-s][-L] [文件 ...]

     

 

Linux其它命令

  1. echo命令
    echo命令的功能是在显示器上显示一段文字,一般起到一个提示的作用。

    USAGE: echo [ -n ] string

     

  2. cal命令
    cal命令的功能是显示某年某月的日历。

    用法:cal [ [月] 年 ]

     

  3. date命令
    date命令的功能是显示和设置系统日期和时间。

    用法: date [-u] mmddHHMM[[cc]yy][.SS] date [-u] [+format] date -a [-]sss[.fff]

     

  4. clear命令
    clear命令的功能是清除屏幕上的信息,它类似于DOS中的 cls命令。清屏后,提示符移动到屏幕左上角。

     

 

常用编程命令

  1. gcc 命令
    gcc 命令的常用选项 GCC 是 GNU 的 C 和 C++ 编译器。实际上,GCC 能够编译三种语言:C、C++ 和 O bject C(C 语言的一种面向对象扩展)。利用 gcc 命令可同时编译并连接 C 和 C++ 源程序。

    gcc 命令的常用选项解释 -ansi 只支持 ANSI 标准的 C 语法。这一选项将禁止 GNU C 的某些特色, 例如 asm 或 typeof 关键词。

    -c 只编译并生成目标文件。

    -DMACRO 以字符串“1”定义 MACRO 宏。

    -DMACRO=DEFN 以字符串“DEFN”定义 MACRO 宏。

    -E 只运行 C 预编译器。

    -g 生成调试信息。GNU 调试器可利用该信息。

    -IDIRECTORY 指定额外的头文件搜索路径DIRECTORY。

    -LDIRECTORY 指定额外的函数库搜索路径DIRECTORY。

    -lLIBRARY 连接时搜索指定的函数库LIBRARY。

    -m486 针对 486 进行代码优化。

    -o FILE 生成指定的输出文件。用在生成可执行文件时。

    -O0 不进行优化处理。

    -O 或 -O1 优化生成代码。

    -O2 进一步优化。

    -O3 比 -O2 更进一步优化,包括 inline 函数。

    -shared 生成共享目标文件。通常用在建立共享库时。

    -static 禁止使用共享连接。

    -UMACRO 取消对 MACRO 宏的定义。

    -w 不生成任何警告信息。

    -Wall 生成所有警告信息。

     

  2. g++ 命令
    gcc 命令只能编译 C++ 源文件,而不能自动和C++ 程序使用的库连接。因此,通常使用 g++ 命令来完成 C++ 程序的编译和连接,该程序会自动调用 gcc 实现编译。

     

  3. perl 命令
    perl命令用令用来解释perl代码并执行

    Usage: E:/Perl/bin/perl.exe [switches] [--] [programfile] [arguments]

    -0[octal] specify record separator (/0, if no argument)

    -a autosplit mode with -n or -p (splits $_ into @F)

    -C[number/list] enables the listed Unicode features

    -c check syntax only (runs BEGIN and CHECK blocks)

    -d[:debugger] run program under debugger

    -D[number/list] set debugging flags (argument is a bit mask or alphabets)

    -e program one line of program (several -e's allowed, omit programfile)

    -f don't do $sitelib/sitecustomize.pl at startup

    -F/pattern/ split() pattern for -a switch (//'s are optional)

    -i[extension] edit <> files in place (makes backup if extension supplied)

    -Idirectory specify @INC/#include directory (several -I's allowed)

    -l[octal] enable line ending processing, specifies line terminator

    -[mM][-]module execute `use/no module...' before executing program

    -n assume 'while (<>) { ... }' loop around program

    -p assume loop like -n but print line also, like sed

    -P run program through C preprocessor before compilation

    -s enable rudimentary parsing for switches after programfile

    -S look for programfile using PATH environment variable

    -t enable tainting warnings

    -T enable tainting checks

    -u dump core after parsing program

    -U allow unsafe operations

    -v print version, subversion (includes VERY IMPORTANT perl info)

    -V[:variable] print configuration summary (or a single Config.pm variable)

    -w enable many useful warnings (RECOMMENDED)

    -W enable all warnings

    -x[directory] strip off text before #!perl line and perhaps cd to directory

    -X disable all warnings

     

 


目录与文件基础

Linux的文件系统是从Unix的文件系统发展而来的。Unix对计算机技术的主要贡献之一就是它文件系统的设计。Unix提供的是一种树型层次的目录结构,文件通常是数据的一个容器,而目录是文件和其他目录的一个容器。目录结构如下图示意:

 

文件系统结构

在Unix系统中,文件被视为无结构的字符流,而文件系统是由一组文件和存放这些文件的磁盘组成的。每个物理磁盘可以包含一个或者多个文件系统。系统核心在逻辑上只涉及文件系统,而不涉入磁盘,把第个文件系统都当作由一个逻辑设备号标识的逻辑设备。由磁盘驱动程序实现逻辑设备与物理设备地址间的转换。Unix文件系统具有如下结构:引导块(boot block),超级块(super block),索引节点表(inode list),数据块(data block)

 

索引节点与目录

索引节点以静止形态存储于磁盘上,核心把它们读进内存索引节点表中以操作它们,索引节点与磁盘关系的如下图示意:

 

连接文件及目录

系统调用link在文件系统结构中将一个文件连接到另外一个新的名字上,也就是为被连接文件的索节点创建一个新的目录项。通过连接操作,一个文件可以有两个以上的不同的文字,系统可以通过其中的任意一个名字来访问,这种为索引节点创建新目录项的连接方式称为“硬连接”

另外一种连接方式“符号连接”,内核为新名字创建一个新的目录项,但是目录项中不含有索引节点号,而是含有从当前目录下被连接文件的路径名。符号连接可以跨文件系统,但是硬连接不能跨文件系统。

 


Apache服务器的配置

  • DNSDNS(域名服务系统)是用于将域名转换为IP的服务
    工作原理:有三种不同的工作方式:一是在本地机器的/etc/hosts文件中进行设置,这样可以不同过连接域名服务器直接连接相应的IP地址;二是发出连向DNS服务器的申请,由DNS负责解析域名。三是通过NIS(网络信息系统)进行域名解析。配置DNS主要由以下几个文件决定: etc/hosts,/etc/resolv.conf,etc/nsswitch.conf,etc/named.conf等一些列文件决定

     

  • 配置FTP服器
    默认情况下,FTP服务器程序wu-ftp已经安装在系统中。如果不能确定,检杳文/etc/xinet.d/wu-ftp是否存在。如果存在,用文本编辑器打开它:
            #default:on
            #description: The wu-ftpdFTPserver serversFTPconnections.It Uses/
            # normal, unencrypted usernames and passwords for authentication.
            service ftp
            {
                    disable         = yes
                    socket_type     = stream
                    wait            = no
                    user            = root
                    server          = /usr/sbin/in.ftpd
                    server_args     = -l -a
                    log_on_sucess   += DURATION USERID
                    log_on_failure  += USERID
                    nice            = 10
            }

    将文件修改为上述如上所示的内容后,FTP服务器的配置就成功了,但是运行前还需重新启动

     

  • 配置邮件服务器
    电子邮件(Electronic Mail)互连网上应用最广泛的服务之一。Linux对电子邮件的收发以及服务器配置都有很好的支持。Linux下邮件服务的使用可以用如下命令给互连网的其他用户发信:$mail fred@abc.com 然后根据相应的条目填写。信件写完后在新的一行输入:&q就可以发送了。配置方法邮件系统的配置关键是sendmail(一种linux下常用的邮件程序)的配置。它的配置文件sendmail.cf是个比较复杂的配置文件,有着自身相关的语法和习惯用语

     

  • TELNET服务
    TELNET(远程终端连接服务)是目前使用非常广泛的一种服务。具有连接方便,传输速度快等特点,同时在远程管理和高校BBS上应用非常广泛。工作原理 TELNET是在应用层的一种明文传输的协议,默认情况下,遵循TCP协议连接远程主机的23端口进行对话。配置方法由于TELNET是最基础的几个服务之一,所以默认情况下系统都已经安装了TELNET的组件。如果不能对远方主机使用TELNET,则可以检查一下本机的防火墙等设置。端口的更改都在 etc/services文件下。

     

  • http服务
    在Linux下同样可以通过http协议登陆超文本网站,浏览网页以及其他各类服务。Linux访问HTTP网站可以在x-windows下通过netscape作浏览器浏览网页。在控制台下可以用lynx来访问网站,但不能观看超文本内容(如图片等)配置方法如果要架设一个网站,可以安装配置Apache或tomcat等服务软件,同时设置好防火墙,就可以开设相关服务了。

     

 


Unix进程通信事例

 

事例1

题目:桌上有一只盘子,可放五个水果,爸爸专放苹果,妈妈专放桔子,一个儿子专吃桔子,女儿专吃苹果,用p,v 操作实现(代码见附录1。)

程程序运行结果如下:(运行环境:江苏大学 机房小型机 版本:Sun Microsystems Inc. SunOS 5.8 Generic Patch October 2001)

  1. father进程运行示意图:

  2. mother进程运行示意图

  3. daughter进程运行示意图

  4. son进程运行示意图

 


附录一:

 

``pv.h''

        #include <sys/types.h>
        #include <sys/ipc.h>
        #include <sys/shm.h>
        #include <sys/sem.h>
        #include <errno.h>
        #include <string.h>
        #define SHMKEY 96735 /*共享存储区的键*/
        #define SEMKEY_PLATE 96736 
        #define SEMKEY_SON 96737 
        #define SEMKEY_DAUGHTER 96738 /*信号量数组的键*//*注意:上面的键在系统中必须唯一*/
        #define SEMKEY_MUTEX 96739
        #define BUFF_LEN 10  /*缓冲区可以存放10个产品*/
        #define PRODUCT_LEN 32 /*每个产品是一个字符串:<=32字符*/
        int P(int semid)
        {
          struct sembuf p_buf;
          p_buf.sem_num = 0;
          p_buf.sem_op = -1;
          p_buf.sem_flg = 0;
          if(semop(semid, &p_buf, 1)==-1)/*semop参见课件ppt*/
          {
            perror ("p (semid) falsed");
            exit (1);
          }
          else
            return (0);
        }
        int V(int semid)
        {
          struct sembuf v_buf;/*struct sembuf 参见课件ppt*/
          v_buf.sem_num = 0;
          v_buf.sem_op = 1;
          v_buf.sem_flg = 0;
          if(semop(semid, &v_buf, 1)==-1)
          {
            perror (" v (semid) failed");
            exit (1);
          } 
          else
            return (0);
        }

 

``control.c''

        #include "pv.h"
        void set_sembuf_struct(struct sembuf *sem,int semnum, int semop,int semflg) 
        { 
          /* 设置信号量结构 */ 
          sem->sem_num=semnum; 
          sem->sem_op=semop; 
          sem->sem_flg=semflg; 
        }
        main()
        {
          char *addr, end;
          int shmid;
          int semid_plate, semid_son, semid_daughter,semid_mutex;/*信号量id*/
          struct sembuf sem_tmp;
            
          /*开辟共享存储区*/
          if ((shmid = shmget(SHMKEY, BUFF_LEN * PRODUCT_LEN+2, 0777|IPC_CREAT|IPC_EXCL)) == -1)
          {
            if (errno == EEXIST)
            {
              printf("The Buffer Has Existed!/n");
              printf("Do You Want To Delete The Buffer(Y = yes)?/n====:");
              scanf("%c", &end);
              if(end == 'y' || end == 'Y')
              {
                /* 共享存储区、信号量并不随程序的结束而被删除,如果我们没删除的话, 
                可以用ipcs命令查看,用ipcrm删除 
                */ 
                /*释放缓冲区*/
                shmid = shmget(SHMKEY, BUFF_LEN * PRODUCT_LEN+2, 0777);
                if (shmctl(shmid,IPC_RMID,0) < 0)
                  perror("shmctl:");
                  
                /*同时释放信号量*/   
                semid_mutex = semget(SEMKEY_MUTEX,1, 0777); 
                semid_plate = semget(SEMKEY_PLATE,1, 0777); 
                semid_son = semget(SEMKEY_SON,1, 0777);
                semid_daughter=semget(SEMKEY_DAUGHTER,1,0777);
                semctl(semid_mutex,0,IPC_RMID);
                semctl(semid_plate,0,IPC_RMID);
                semctl(semid_son,0,IPC_RMID);
                semctl(semid_daughter,0,IPC_RMID);
              }
            }
            else 
              printf("Fail To Create Buffer!/n");
            return -1;
          }
          
          addr = (char*)shmat(shmid, 0, 0);/*连接缓冲区*/
          memset(addr, 0, BUFF_LEN * PRODUCT_LEN+2);
          shmdt(addr); /*离开缓冲区*/
          /*创建3个信号量:1个用于对缓冲区互斥,2个用于生产者、消费者同步*/
          
          
          if((semid_plate = semget(SEMKEY_PLATE,1, 0777|IPC_CREAT|IPC_EXCL))==-1) 
          { 
            if (errno == EEXIST)
              printf("The SEMKEY_PLATE Has Existed!/n");
            else 
              printf("Fail To Create SEMKEY_PLATE!/n");
            return -1; 
          } 
          if((semid_mutex = semget(SEMKEY_MUTEX,1, 0777|IPC_CREAT|IPC_EXCL))==-1) 
          { 
            if (errno == EEXIST)
              printf("The SEMKEY_MUTEX Has Existed!/n");
            else 
              printf("Fail To Create SEMKEY_MUTEX!/n");
            return -1; 
          } 
          
          if((semid_son = semget(SEMKEY_SON,1, 0777|IPC_CREAT|IPC_EXCL))==-1) 
          { 
            if (errno == EEXIST)
              printf("The SEM_SON Has Existed!/n");
            else 
              printf("Fail To Create SEM_SON!/n");
            return -1; 
          } 
          
          if((semid_daughter = semget(SEMKEY_DAUGHTER,1, 0777|IPC_CREAT|IPC_EXCL))==-1) 
          { 
            if (errno == EEXIST)
              printf("The SEMKEY_DAUGHTER Has Existed!/n");
            else 
              printf("Fail To Create SEMKEY_DAUGHTER!/n");
            return -1; 
          } 
          
          
          /*给信号量赋初值*/
          set_sembuf_struct(&sem_tmp, 0, BUFF_LEN, 0);/*BUFF_LEN*/
          semop(semid_plate, &sem_tmp,1);
          
          set_sembuf_struct(&sem_tmp, 0, 0, 0);/*0*/
          semop(semid_son, &sem_tmp,1);
          
          set_sembuf_struct(&sem_tmp, 0, 0, 0);/*BUFF_LEN*/
          semop(semid_daughter, &sem_tmp,1);
          
          
          set_sembuf_struct(&sem_tmp, 0, 1, 0);/*1*/  
          semop(semid_mutex, &sem_tmp,1);
          
          return 0;
        }

 

``father.c''

        #include "pv.h"
        main()
        {
          int i = 1;
          while(1) {
                  char *p_buffer;/*共享存储区地址*/
                  unsigned char in;/*生产者存放产品的指针:它的值存放在全局缓冲区第一个字节*/
                  char product[128] = "apple";/*事实只使用32B,128为了避免屏幕输入超过32*/
                  int shmid;/*共享存储区id*/
                  int semid_plate, semid_son, semid_daughter,semid_mutex;/*信号量集合id*/
                  shmid = shmget(SHMKEY, BUFF_LEN * PRODUCT_LEN+2, 0777);/*连接共享存储区:2 存放in,out的值*/
                  p_buffer = (char*)shmat(shmid, 0, 0);/*取共享存储区地址*/
                  semid_mutex = semget(SEMKEY_MUTEX,1, 0777);/*获取全局信号量id*/
                  semid_plate = semget(SEMKEY_PLATE,1, 0777);
                  semid_son = semget(SEMKEY_SON,1, 0777); 
                  semid_daughter = semget(SEMKEY_DAUGHTER,1, 0777);
          /*从屏幕接收产品*/
                printf("Put food (a string ,length <= 32B):/tapple/n");
                printf("father put an apple for %d time/n", i);
                i++;
                //product = "apple";/*128的意义在此,此函数不检查字符串长度*/
                /*进入临界区*/
                P(semid_plate);/*对私有信号量作P操作*/
                P(semid_mutex);/*对公有信号量作P操作*//*二者顺序不能换*/
                in = (unsigned char)(*p_buffer);
                in =( in+1)%BUFF_LEN;
                strncpy(p_buffer + 2 + in * PRODUCT_LEN, product, PRODUCT_LEN);
                //in = (in + 1) % BUFF_LEN;
                *p_buffer = (char)in;
                shmdt(p_buffer); /*离开缓冲区*/
                /*离开临界区*/
                V(semid_daughter);
                V(semid_mutex);
                sleep(1);
                i++;
                }
         
        }

 

``mother.c''

        /*生产者:mother.c*/
        #include "pv.h"
        main()
        {
          int i = 1;
          while(1) {
                  char *p_buffer;/*共享存储区地址*/
                  unsigned char in;/*生产者存放产品的指针:它的值存放在全局缓冲区第一个字节*/
                  char product[128] = "orange";/*事实只使用32B,128为了避免屏幕输入超过32*/
                  int shmid;/*共享存储区id*/
                  int semid_plate, semid_son, semid_daughter,semid_mutex;/*信号量集合id*/
                  shmid = shmget(SHMKEY, BUFF_LEN * PRODUCT_LEN+2, 0777);/*连接共享存储区:2 存放in,out的值*/
                  p_buffer = (char*)shmat(shmid, 0, 0);/*取共享存储区地址*/
                  semid_mutex = semget(SEMKEY_MUTEX,1, 0777);/*获取全局信号量id*/
                  semid_plate = semget(SEMKEY_PLATE,1, 0777);
                  semid_son = semget(SEMKEY_SON,1, 0777); 
                  semid_daughter = semget(SEMKEY_DAUGHTER,1, 0777);
              /*从屏幕接收产品*/
              //printf("Put food (a string ,length <= 32B):/n====:/n");
              printf("Put food (a string ,length <= 32B):/torange/n");
              printf("mother put an orange for %d time/n", i);
              i++;
              
              //product = "orange";/*128的意义在此,此函数不检查字符串长度*/
              
              /*进入临界区*/
              P(semid_plate);/*对私有信号量作P操作*/
              P(semid_mutex);/*对公有信号量作P操作*//*二者顺序不能换*/
             
              p_buffer++;
             in = (unsigned char)(*p_buffer);
             in =(in+BUFF_LEN);
              in=(in-1)%BUFF_LEN;
              strncpy(p_buffer + 1 + in * PRODUCT_LEN, product, PRODUCT_LEN);
              //in = (in + 1) % BUFF_LEN;
              *p_buffer = (char)in;
              p_buffer--;
              shmdt(p_buffer); /*离开缓冲区*/
              
              /*离开临界区*/
              V(semid_son);
              V(semid_mutex);
              sleep(1);
              i++;
              }  
        }

 

``daughter.c''

        /*消费者:daughter.c*/
        #include "pv.h"
        /*下面的P,V是对系统调用的简单封装*/
        main()
        {
          int i = 1;
          while(1) {
                  char *p_buffer;/*共享存储区地址*/
                  unsigned char out;/*消费者取出产品的指针:它的值存放在全局缓冲区第二个字节*/
                  char product[33];/*它的数据从缓冲区中取*/
                  int shmid;/*共享存储区id*/
                  int semid_plate, semid_son, semid_daughter,semid_mutex;/*信号量集合id*/
                    
                  shmid = shmget(SHMKEY, BUFF_LEN * PRODUCT_LEN+2, 0777);/*连接共享存储区:2 存放in,out的值*/
                  p_buffer = (char*)shmat(shmid, 0, 0);/*取共享存储区地址*/
                  semid_mutex = semget(SEMKEY_MUTEX,1, 0777);/*获取全局信号量id*/
                  semid_plate = semget(SEMKEY_PLATE,1, 0777);
                  semid_son = semget(SEMKEY_SON,1, 0777); 
                  semid_daughter = semget(SEMKEY_DAUGHTER,1, 0777); 
                  
                 
                  /*进入临界区*/
                  P(semid_daughter);/*对私有信号量作P操作*/
                  P(semid_mutex);/*对公有信号量作P操作*//*二者顺序不能换*/
                  
                  //p_buffer++;
              printf("father put an apple in plate/n");
                  out = (unsigned char)(*p_buffer);
                  strcpy(product, p_buffer + 2 + out * PRODUCT_LEN);
                  out = (out-  1) % BUFF_LEN;
                  *p_buffer = (char)out;
                 // p_buffer--;
                  shmdt(p_buffer); /*离开缓冲区*/
                  
                   /*离开临界区*/
                  V(semid_plate);
                  V(semid_mutex);
                  /*消费产品:在屏幕上输出*/
                  printf("daughter eat the apple for %d time/n", i);
                  i++;
                  sleep(1);
                  }
        }

 

``son.c''

        /*消费者:son.c*/
        #include "pv.h"
        main()
        {
           int i = 1;
           while(1) {
                  char *p_buffer;/*共享存储区地址*/
                  unsigned char out;/*消费者取出产品的指针:它的值存放在全局缓冲区第二个字节*/
                  char product[33];/*它的数据从缓冲区中取*/
                  int shmid;/*共享存储区id*/
                  int semid_plate, semid_son, semid_daughter,semid_mutex;/*信号量集合id*/
                    
                  shmid = shmget(SHMKEY, BUFF_LEN * PRODUCT_LEN+2, 0777);/*连接共享存储区:2 存放in,out的值*/
                  p_buffer = (char*)shmat(shmid, 0, 0);/*取共享存储区地址*/
                  semid_mutex = semget(SEMKEY_MUTEX,1, 0777);/*获取全局信号量id*/
                  semid_plate = semget(SEMKEY_PLATE,1, 0777);
                  semid_son = semget(SEMKEY_SON,1, 0777); 
                  semid_daughter = semget(SEMKEY_DAUGHTER,1, 0777);
          /*进入临界区*/
                  P(semid_son);/*对私有信号量作P操作*/
                  P(semid_mutex);/*对公有信号量作P操作*//*二者顺序不能换*/
                  
                 p_buffer++;
                  out = (unsigned char)(*p_buffer);
                  strcpy(product, p_buffer + 1 + out * PRODUCT_LEN);
                  out = (out + 1) % BUFF_LEN;
                  *p_buffer = (char)out;
                 p_buffer--;
                  shmdt(p_buffer); /*离开缓冲区*/
                  
                   /*离开临界区*/
                  V(semid_plate);
                  V(semid_mutex);
                  printf("son eat an orange for %d time/n", i);
                  i++;
                  sleep(1);
                  i++;
                  }
        }

 

``comp''

        gcc -o c control.c
        gcc -o f father.c
        gcc -o m mother.c
        gcc -o s son.c
        gcc -o d daughter.c
        c

 


课程设计总结

通过近一个星期的课程设计,自己是受益颇深,一方面熟悉了Linux/Unix系统,并对其有了较为深刻的了解,自已再也不会局限于windows这一操作系统,在操作系统方面多了一种选择,在今后的学习,工作中,也就多了一个解决问题的利器。另一方面,进程同步程序的真正实现,为我解决了许多以前感到神秘莫测,百思不得求解的问题,比方说 相互独立进程之间相互发送信号,通信问题,客户与主机之间的联系等等!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值