Linux是一个通用操作系统。一个操作系统要负责任务调度、内存分配、处理外围设备I/O等操作。操作系统通常由内核和系统程序(设备驱动、底层库、shell、服务程序等)两部分组成。
1 Linux优点
- 通用操作系统,不跟特定的硬件绑定。
- 用C语言编写,有可移植性,有内核编程接口。
- 支持多用户和多任务,支持安全的分层文件系统。
- 大量的实用程序,完善的网络功能以及强大的支持文档。
- 可靠的安全性和良好的稳定性,对开发者更友好。
2 Linux基础命令
Linux系统的通用命令格式:命令名称 [命名参数][命令对象]
获取登录信息:w / who / last
查看进程:ps
查看命令的说明:whatis
- whatis ps
查看命令的位置:which / whereis
- whereis python
查看帮助文档:man / info / apropos
- ps –help
- man ps
- info ps
切换用户:su
- su Tom
以管理员身份执行命令:sudo
- sudo ls /root
登入登出相关:logout / exit / adduser / userdel / passwd / ssh
查看系统和主机名:uname / hostname
重启和关机:reboot / init 6 / shutdown / init 0
查看历史命令:history
3 Linux实用程序
3.1 文件和文件夹操作
创建/删除目录:mkdir / rmdir
创建/删除文件:touch / rm
- touch命令用于创建空白文件或修改文件时间。
- 在Linux系统中一个文件有三种时间:
- 更改内容的时间(mtime)
- 更改权限的时间(ctime)
- 最后访问时间(atime)
切换和查看当前工作目录:cd / pwd
查看目录内容:ls
查看文件内容:cat / head / tail / more / less
拷贝/移动文件:cp / mv
查看文件及内容:find / grep
符号链接:ln
压缩和归档:gzip / gunzip / xz / tar
其他工具:sort / uniq / diff / file / wc
3.2 管道和重定向
- 管道的使用:|
- 输出重定向和错误重定向:> / 2>
- 输入重定向:<
3.3 别名
- alias
- unalias
- alias nasm=’/usr/local/bin/nasm’
3.4 其他程序
- 时间和日期:date / cal
- 录制操作脚本:script
- 给用户发送消息:mesg / write / wall / mail
4 文件系统
4.1 目录结构
- /bin - 基本命令的二进制文件
- /boot - 引导加载程序的静态文件
- /dev - 设备文件
- /etc - 配置文件
- /home - 用户主目录的父目录
- /lib - 共享库文件
- /lib64 - 共享64位库文件
- /lost+found - 存放未链接文件
- /media - 自动识别设备的挂载目录
- /mnt - 临时挂载文件系统的挂载点
- /opt - 可选插件软件包安装位置
- /proc - 内核和进程信息
- /root - root账户主目录
- /run - 存放系统运行时需要的东西
- /sbin - 超级用户的二进制文件
- /sys - 设备的伪文件系统
- /tmp - 临时文件夹
- /usr - 用户应用目录
- /var - 变量数据目录
4.2 访问权限
- chmod
- chown
4.3 磁盘管理
- 列出文件系统的磁盘使用状况 - df
- 磁盘分区表操作 - fdisk
- 格式化文件系统 - mkfs
- 文件系统检查 - fsck
- 挂载/卸载 - mount / umount
5 环境变量
- HOME
- SHELL
- HISTSIZE
- RANDOM
- PATH
6 软件安装和配置
6.1 yum
- yum update
- yum install / yum remove
- yum list / yum search
- yum makecache
6.2 rpm
- rpm -ivh –force –nodeps
- rpm -e
- rpm -qa | grep
7 网络访问和管理
- 通过网络获取资源 - wget。
- -b 后台下载模式
- -O 下载到指定的目录
- -r 递归下载
- 显示/操作网络配置(旧) - ipconfig。
- 显示/操作网络配置(新) - ip。
- 网络可达性检查 - ping。
- 查看网络服务和端口 - netstat。
- 安全文件拷贝 - scp。
- 安全文件传输 - sftp。
8 课程学习
- 文件系统的启动过程:
- BIOS –> MBR –> Boot loader –> Init process –> Done
- BIOS检查设备 –> 加载并启动MBR –> 加载MBR中的bootloader(常见有LILO和GRUB两种) –> 启动Linux内核 –> 完成(现在控制权已交给内核)
- 硬链接和符号链接
- 硬链接(不同的文件名对应同一个inode,不能跨越文件系统,对应系统调用link):
- ln 可以为文件创建硬链接,但不能为目录创建,硬链接并没有建立新文件
- 创建硬链接后,文件的inode会被多个文件项共用
- 文件的硬链接数可以在ls -l后的列表的第二列看到,无额外链接的文件的链接数为1
- 硬链接可以理解为多个文件指向同一个物理地址,所以不能对目录做硬链接,也不可以在不同的文件系统之间做硬链接
- 软链接/符号链接(存储被链接文件的文件名与路径,可跨越文件系统,对应系统调用symlink):
- ln -s 将一个路径名链接到一个文件
- 软链接文件是一个文本文件,包含了链接时的源文件的路径名,而源文件才是实际包含数据的文件
- 软链接文件在ls -l中第一列显示一个l,表示符号链接文件(硬链接的第一列依然是-,表示文件)
- 软链接可以理解为快捷方式(通过它能迅速找到源文件,而不是直接找物理地址),它本身确实是一个新的文件,它的大小就是符号链接中路径的字节数,所以它具有和源文件不同的inode号
- 软链接可以对目录进行,也可以在不同的文件系统之间做符号链接
- 硬链接(不同的文件名对应同一个inode,不能跨越文件系统,对应系统调用link):
- 文件属性(ls -l):文件类型 权限 硬链接数目 所有者 用户组 文件大小 修改时间 文件名
- umask命令与默认权限
- umask命令用来设置限制新建文件权限的掩码
- 当新文件创建时,其最初的权限由默认权限与umask掩码共同决定。文件的默认权限是666,即rw-rw-rw-,目录的默认权限是777,即rwxrwxrwx。而在此基础之上,umask设置的掩码将会从以上权限中把相应位置的权限拿走(即删去指定位的权限)
- 如umask设置的掩码为022,那么新文件的权限上用户组和其他用户的write权限就会被拿走,也就是文件权限变成了644,即rw-r-r-,而新建文件夹的权限也变成了rwxr-xr-x,即755
- umask掩码的作用是“拿走”相应位置上的权限(不管之前有没有,最终这个位置没有权限)
- 数字表示:umask 将会显示删掉的权限(如掩码022)
- 符号表示:umask -S 将会显示剩下的权限(如u=rwx,g=rx,o=rx)
- 三种执行shell脚本的方法
- 作为可执行程序:
- chmod +x ./x.sh 使脚本具有可执行权限
- ./x.sh 执行脚本
- 作为解释器参数:
- sh x.sh 或 /bin/sh x.sh
- 这种方式不需要在脚本第一行指定解释器参数,即#!/bin/bash
- source x.sh 或 . x.sh
- 作为可执行程序:
- shell中的引号:
- 单引号:单引号中的任何字符都会原样输出,转义失败,变量也是无效的
- 双引号:里面可以有变量,也可以出现转义字符(即$ 、``、 \将分别被bash解释)
- 两个接口:
- 用户与内核的接口:系统调用
- 用户与操作系统的接口:shell
- 硬盘属于块设备 (block devices)
- 找出 /etc/my.conf 文件属于哪个包 (package):rpm -qf /etc/my.conf
- 用于改变 IDE 硬盘的设置:hdparm
- 列出定义在以后特定时间运行一次的所有任务:atq
- 改变命令提示符:set PS1=”[\u\w\t]\$” ; export PS1
- /etc/passwd和/etc/shadow两个文件的权限:-rw-r–r– , -r————
- 查看Linux的启动信息:dmesg
- 显示系统中各个分区中inode的使用情况:df -i
- 显示 passwd 文件的结构:man 5 passwd
- 检测基本网络连接:netstat
- 网络服务的daemon是:netd
- 定义bash环境的用户文件是:.bashrc & .bash_profile
- 卸载一个内核模块:rmmod
- 显示所有装载的模块:lsmod
9 查缺补漏
信号量属于SYSTEM V进程间通讯方式
Linux系统中,用户文件描述符0、1、2分别表示:标准输入、标准输出、标准错误输出
卸载一个软件包:rpm -e
关于i节点:
- i节点能描述文件占用的块数
- i节点描述了文件大小和指向数据块的指针
- 通过i节点实现文件的逻辑结构和物理结构的转换
- 这是错误的:i节点和文件是一一对应的
在vi编辑器中的命令模式下,重复上一次对编辑的文本进行的操作,可使用 . 命令
Linux系统的进程类型:守护进程、交互进程、批处理进程
关于/etc/fstab文件描述:启动时按fstab文件描述内容加载文件系统
在Shell脚本中,用来读取文件内各个域的内容并将其赋值给Shell变量的命令是:read
在Linux2.4.0版本中:
- 进程有6种状态:可运行、可中断等待、不可中断等待、僵死、暂停、独占(替换了原来的交换)
- 进程使用exit系统调用后进入僵死状态
在Linux 中管道分为2种类型,若创建或打开时获得的描述符存放在fd中,则fd[1]是管道写描述符
Linux为用户提供的接口有:shell、XWINDOW、系统调用
超级块是描述文件系统属性信息的数据结构,索引节点是描述文件属性信息的数据结构
显示文件系统空间使用情况:df 命令
显示目录或文件占用磁盘空间容量:du 命令
命令组合(命令表)将建立新的子进程来执行命令
磁盘限额管理可以使用quota软件工具,其中硬限额的容量应该大于软限额
交换线程通过三种途径来缩减已使用的内存页面:
- 减少buffer cache和page cache的大小
- 换出系统V类型的内存页面
- 换出或丢弃进程占用的页面
安装Linux系统对硬盘分区时,必须有两种分区类型:Linux原始分区(根分区) 和 Linux交换分区
在Linux的两种链接文件中,只能实现对文件链接的一种方式是:软链接(符号链接)
Linux主要采用了请求调页和写时复制两种动态内存管理技术实现了物理内存以On demand方式动态分配
对于System V类型的共享内存页面,Linux基于Clock算法决定哪些页面应当被换出物理内存
在Linux与中断相关的三个核心数据结构中,用做抽象的中断控制器的数据结构是hw_interrupt_type,它包含一系列处理中断控制器特有的操作
通过将request动态链入块设备控制结构blk_dev_struct,Linux设备管理器有效的实现了物理设备和缓冲区之间的异步读写通讯
归档与解压命令:
压缩
- 命令格式:tar -zcvf 压缩命令的目标文件 待压缩的源文件
- 例如:tar -zcvf wang.tar.gz /home/stud1/wang将/home/stud1/wang目录做归档压缩,压缩后生成wang.tar.gz文件,并将此文件保存到/home目录下
解压:
- 命令格式:tar -zxvf 待解压文件
- 例如:tar -zxvf wang.tar.gz
对于Shell脚本程序,若输入参数数量多于9个,则程序遍历每个参数可通过使用shift命令实现
在System V进程通讯方式中,ipc_perm结构描述对一个系统IPC对象的存取权限,而用于定位IPC对象的引用标志符key可以依据键值分成公有、私有两种类型
底半技术:
- 把一个中断处理分为2部分:顶半部分和底半部分
- 优势:
- 使中断的总延迟时间最小化
- 加快对中断请求的响应速度
- 合并某些中断处理
Vi的工作模式
- 三种工作模式:命令模式、输入模式、末行模式
- 如何切换模式:在命令模式下输入a、A、i、I、o、O等命令之一可以进入输入模式,在输入模式下按Esc键回到命令模式;在命令模式下输入:进入末行模式,末行命令执行完后回到命令模式
Shell变量可以分为:用户自定义变量、环境变量、位置变量、特殊变量,其中位置变量是指命令行上传递给程序的参数
从内核实现的角度说明Linux进程共享文件的方式:
- 进程通过多个file结构共享一个inode
- 进程共享一个file结构
实时信号、非实时信号、可靠信号、不可靠信号:
- 实时信号目前未用
- 非实时信号编号1~31、0表示空信号,非实时信号没有排队机制,可能丢失
- 不可靠信号0~31,不可靠信号每次处理完信号后,都将对信号的响应设置为默认动作,需要在结尾再次安装信号
- 可靠信号32~63,可靠信号和不可靠信号的安装函数也不同,主要在于信号类型取值,而不在于操纵他们的API
Kswapd核心线程的动态特性:主要通过nr_async_pages参考free_pages_high和free_pages_low来判断交换数量和线程睡眠时间
- Nr_async_pages大于free_pages_high时每次释放6个页面,在free_pages_high和free_pages_low之间时释放3个,小于free_pages_low时不释放
- 若Kswapd被唤醒后发现Nr_async_pages小于free_pages_low则睡眠时间加班,反之则逐步延长睡眠时间
Linux通过i节点表将文件的逻辑结构和物理结构进行转换:
- i节点是一个64字节长的表,表中包含了文件的相关信息,其中有文件的大小、文件所有者、文件的存取许可方式以及文件的类型等重要信息
- 在i节点表中最重要的内容是磁盘地址表。在磁盘地址表中有13个块号,文件将以块号在磁盘地址表中出现的顺序依次读取相应的块。若文件空间大于13块,则分别用1次、2次、3次间接块实现对数据块的定位
- 此后,Linux文件系统通过把i节点和文件名进行连接,当需要读取该文件时,文件系统在当前目录表中查找该文件名对应的项,由此得到该文件相对应的i节点号,通过该i节点的磁盘地址表把分散存放的文件物理块连接成文件的逻辑结构
在Linux系统中运行下面程序,最多可产生多少个进程?画出进程家族树
1
main()
2
{
3
fork();
4
fork();
5
fork();
6
}
最多可以产生7个进程,家族树如下:
统计文件file中所有包含字符串”WHU”的行数:grep WHU file | wc -l
可以把两个文本文件合并成一个文件的命令是:cat
为了统计文件系统中未用的磁盘空间,可以用命令:du
Linux中内核进程init的进程标识符是:1
proc文件系统存在于:内存
只列出目录下的子目录:ls -F | grep /$
统计某个目录下的文件数:ls -l * | grep “^-“ | wc -l
统计某个目录下的目录数:ls -l * | grep “^d” | wc -l
内核分为进程调度、内存管理、虚拟文件系统、网络接口、进程间通信等五个子系统
在Linux 中,进程的优先数值越小,其相应的优先权越高
在Linux 中,用户账号包括超级用户、系统用户和普通用户
信号与中断
- 相似点
- 采用了相同的异步通信方式
- 当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序
- 都在处理完毕后返回到原来的断点
- 对信号或中断都可进行屏蔽
- 区别
- 中断有优先级,而信号没有优先级,所有的信号都是平等的
- 信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行
- 中断响应是及时的,而信号响应通常都有较大的时间延迟
- 相似点
Linux的引导程序:LILO和GRUB
- LILO没有交互式命令界面,而Grub拥有
- LILO不支持网络引导,而Grub支持
- LILO将关于可以引导的操作系统位置的信息物理上存储在MBR中,如果修改了LILO配置文件,必须将LILO第一阶段引导加载程序重写到MBR。相对于Grub,这是一个更为危险的选择,因为错误配置的MBR可能会让系统无法引导。而使用Grub,如果配置文件配置错误,则只是默认转到Grub命令行界面。
在LINUX运行的7个级别中,X—WINDOWS图形系统的运行级别为:5
选择 “文本登录方式” 设定系统开始运行级为:3
若在文字界面下,需要键入何种指令才能进入图形界面(Xwindow):startx
Linux内核引导时,从文件/etc/fstab中读取要加载的文件系统
用来存放系统所需要的配置文件和子目录的目录是/etc
关闭linux系统(不重新启动)使用的命令:halt
该命令可以实现关机:init 0
存放Linux基本命令的目录是:/bin
在shell编程时,使用方括号表示测试条件的规则是:方括号两边必有空格
当系统管理员需升级内核版本和改变系统硬件配置时,应重新编译内核
Slab分配器思想
- 小对象的申请和释放通过slab分配器来管理
- slab分配器有一组高速缓存,每个高速缓存保存同一种对象类型,如i节点缓存、PCB缓存等
- 内核从它们各自的缓存中分配和释放对象。系统分配对象时就从slab中取得。首先从这个cache中部分满的slab中分配,如果没有这样的slab, 便从空的slab中分配,如果也没有,就创建一个新的slab来分配即可。由于每个对象在释放时几乎处于分配好并且初始化好的状态,还可以节省不少初始化的时间
- 每种对象的缓存区由一连串slab构成,每个slab由一个或者多个连续的物理页面组成。这些页面种包含了已分配的缓存对象,也包含了空闲对象
Linux系统进程调度的总体思想
实时进程优先于普通进程,实时进程以进程的紧急程度为优先顺序,普通进程以进程平等占用CPU时间为基本调度原则。
Linux 内核的主要组成部分
进程调度负责控制进程对CPU的访问,调度程序使用一种策略确保所有的进程都能公平的访问CPU,并且确保内核在任意时刻能执行必要的硬件操作。
内存管理负责管理系统的物理内存,实现多进程安全享享计算机的内存。
虚拟文件系统通过将各种设备抽象为一种公共接口,从而屏蔽了各种硬件设备的细节。虚拟文件系统可以分为逻辑文件系统和设备驱动程序两部分。
网络接口提供了对各种网络标准的存取和各种网络硬件的支持,实现了对各种网络标准和网络硬件的访问。网络接口可分为网络协议和网络驱动程序。网络协议部分负责实现每一种可能的网络传输协议。网络设备驱动程序负责与硬件设备通讯,每一种可能的硬件设备都有相应的设备驱动程序。
进程间通信子系统实现了系统内部进程间的多种通信机制。
这五个子系统互相依赖,但相对来说进程调度处在比较重要的地位。其他子系统需要挂起和恢复进程的运行都必须依靠进程调度子系统的参与。
基于虚拟内存技术的程序执行两次映射
- 应用程序向虚拟内存映射:用虚拟地址为程序编址,映射到虚拟内存空间;确定其代码段、数据段和堆栈段的地址空间,系统以逻辑地址访问虚拟内存中的某个程序段
- 把要运行的程序段复制到物理内存,映射到物理内存空间,确定程序的物理地址。虚拟内存逻辑地址与物理地址的对应记录表;系统自物理内存地址读取所需数据
Buddy算法-伙伴算法
- 把内存中所有页面按照2n划分,其中n=0~5,每个内存空间按1个页面、2个页面、4个页面、8个页面、16个页面、32个页面进行六次划分。划分后形成了大小不等的存储块,称为页面块,简称页块。包含1个页面的页块称为1页块,包含2个页面的称为2页块,依此类推。每种页块按前后顺序两两结合成一对Buddy“伙伴”
- 每个页块组用一个双向循环链表进行管理,共有6个链表,分别为1、2、4、8、16、32页块链表。分别挂到free_area[] 数组上
- 内存分配时,系统按照Buddy算法,根据请求的页面数在free_area[]对应的空闲页块组中搜索。若请求页面数不是2的整数次幂,则按照稍大于请求数的2的整数次幂的值搜索相应的页面块组。当相应页块组中没有可使用的空闲页面块时就查询更大一些的页块组,在找到可用的空闲页面块后,分配所需页面
- 当某一空闲页面块被分配后,若仍有剩余的空闲页面,则根据剩余页面的大小把它们加入到相应页块组中
- 内存页面释放时,系统将其做为空闲页面看待。检查是否存在与这些页面相邻的其它空闲页块,若存在,则合为一个连续的空闲区按Buddy算法重新分组
linux使用的进程间通信方式
- 管道(pipe)和有名管道(FIFO)
- 信号(signal)
- 消息队列:msgget可以创建一个新队列或打开一个存在的队列. msgctl类似于驱动程序中的ioctl函数, 可对消息队列执行多种操作. 调用msgsnd将数据放到消息队列中. 调用msgrcv将从消息队列中取消息
- 共享内存:linux进程调用shmget(Shared Memory GET,获取共享内存)来分配一个共享内存块。shmat(SHared Memory Attach,绑定到共享内存)。shmctl(”Shared Memory Control”,控制共享内存)函数会返回一个共享内存块的相关信息。同时 shmctl 允许程序修改这些信息
- 信号量
- 套接字(socket)
运行级别
运行级别是操作系统当前运行的功能级别,从0到6有不同的功能,在/etc/inittab文件中定义。运行级别可以由超级用户通过 telinit 命令来转换,此命令可以将转换信号传递给init,告诉它切换到哪个运行级别。也可以通过修改/etc/inittab文件来进行缺省运行级别的修改。
- 0 - 关机(千万不要把initdefault 设置为0 )
- 1 - 单用户模式,root权限,用于系统维护,禁止远程登陆
- 2 - 多用户模式,但是没有 NFS
- 3 - 完全多用户模式,标准运行级别,登录后进入命令行模式
- 4 - 没有用到,保留
- 5 - 多用户模式,X11控制台,登录后进入图形GUI模式
- 6 - 重启(千万不要把initdefault 设置为6 )
11 Shell编程
以用户账号zheng,登录进入linux系统,查看当前登录到系统中的用户和当前系统运行的进程,再退出系统
1
login:zheng
2
Password:口令
3
who
4
ps
5
Ctrl+D
在当前目录/home/zheng下新建一个目录back,将当前目录改为back,在back下新建2个长度为0的文件test1、test2,然后把test2移到其父目录中并改名为file12
1
mkdir back
2
cd back
3
touch test1 test2
4
mv test2 ../file2
统计当前目录/home/zheng下普通文件的数目并显示结果
1
find –type f | wc –l
系统管理员需要增加一个新用户zheng,为其设置初始密码,锁定用户账号uly,并删除用户账号chang
1
useradd zheng
2
passwd zheng
3
passwd –l uly
4
userdel chang
将/home/zheng目录下的所有文件打包压缩成/tmp/zheng.tar.gz,怎么做?从压缩包中恢复,又该怎么做?
1
tar –zcvf /tmp/zheng.tar.gz /home/zheng
2
tar -zxvf /tmp/zheng.tar.gz
Shell程序添加一个新组为class1,添加属于这个组的30个用户,用户名形式为stdxx,xx从01到30
1
!/bin/sh
2
i=1
3
groupadd class1
4
while [ $i -le 30 ]
5
do
6
if [ $i -le 9 ] ;then
7
USERNAME=stu0${i}
8
else
9
USERNAME=stu${i}
10
fi
11
useradd $USERNAME
12
mkdir /home/$USERNAME
13
chown -R $USERNAME /home/$USERNAME
14
chgrp -R class1 /home/$USERNAME
15
i=$(($i + 1)) #或let “i=i+1”
16
done
写一个Shell程序,接收用户从键盘输入的100个整数,求出其总和、最大值及最小值
1
!/bin/sh
2
read max
3
min=$max
4
sum=$max
5
i=1
6
while [$i –lt 100]
7
do
8
read x
9
sum=`expr $sum + $x`
10
if [ $max –lt $x ]
11
then
12
max=$x
13
fi
14
if [ $ x –lt $min ]
15
then
16
min=$x
17
fi
18
i=`expr $i + 1`
19
done
20
echo "sum = $sum ; max = $max min = $min "
在/home目录下查找文件名为.Profile的文件,找到后删除
1
find /home -name .profile -exec rm {} \;
创建一个用户,用户名为user02,所属私有组和标准组为stuff,用户家目录为/home/user2,用户登陆shell为/bin/bash
1
useradd –g stuff –G stuff -d /home/user2 -s /bin/bash user02
写一个shell脚本,检查给出的串是否为回文(palindrome)
1
! /bin/bash
2
echo "Enter string"
3
read str
4
len=`echo $str | wc -c`
5
len=`expr $len - 1`
6
l=`expr $len / 2`
7
ctr=1
8
flag=0
9
while test $ctr -le $l
10
do
11
a=`echo $str | cut -c$ctr`
12
b=`echo $str | cut -c$len`
13
if test $a -ne $b
14
then flag=1
15
break
16
fi
17
ctr=`expr $ctr + 1`
18
len=`expr $len - 1`
19
done
20
if test $flag -eq 0
21
then echo "String is palindrome"
22
else echo "String not a palindrome"
23
fi
用shell编写小九九乘法表程序
1
!/bin/sh
2
for i in 1 2 3 4 5 6 7 8 9
3
do
4
for j in 1 2 3 4 5 6 7 8 9
5
do
6
if ( test $j -le $i ) then
7
echo -ne `expr $i \* $j` "\t"
8
else
9
echo
10
break
11
fi
12
done
13
done
12 其他
进程编程
1
2
3
int ntimes=0;
4
main(int argc, char *argv[]) {
5
int pid,ppid;
6
int p_action( ), c_action( );
7
signal(SIGUSR1 , p_action); # 在父进程中为信号SIGUSR1绑定函数p_action
8
switch(pid=fork( )) { # 创建子进程
9
case -1: perror("fork failed?");
10
exit(1);
11
case 0: signal(SIGUSR1,c_action);
12
ppid=getppid( );
13
for ( ; ; ) ;
14
default: {
15
for( ; ; ) {
16
pause;
17
sleep(1);
18
kill(pid,SIGUSR1); # 向子进程发送信号SIGUSR1
19
}
20
}
21
}
22
}
23
p_action( ) {
24
printf("parent caught signal #%d\n",++ntimes);
25
}
26
c_action( ) {
27
printf("child caught signal #%d\n",++ntimes);
28
int ppid;
29
ppid = getppid(); # 获取父进程的PID
30
kill(ppid, SIGUSR1);
31
sleep(3);
32
}
父进程无限循环向子进程发送信号,子进程收到信号后向父进程发送相同信号,父子进程之间各自记录全局变量的变化,前6行结果如:
1
child caught signal #1
2
parent caught signal #1
3
child caught signal #2
4
parent caught signal #2
5
child caught signal #3
6
parent caught signal #3
linux 进程及管道应用实例
1
2
3
int main()
4
{
5
int n,fd[2]; // 这里的fd是文件描述符的数组,用于创建管道做准备
6
pid_t pid;
7
char line[100];
8
if(pipe(fd)<0) // 创建管道
9
printf("pipe create error/n");
10
if((pid=fork())<0) // 利用fork()创建新进程
11
printf("fork error/n");
12
else if(pid>0){ // 这里是父进程,先关闭管道的读出端,然后在管道的写端写入“hello world"
13
close(fd[0]);
14
write(fd[1],"hello word/n",11);
15
}
16
else{
17
close(fd[1]); // 这里是子进程,先关闭管道的写入端,然后在管道的读出端读出数据
18
n= read(fd[0],line,100);
19
write(STDOUT_FILENO,line,n);
20
}
21
exit(0);
22
}