第一章
(1)软件包的管理方式方面,Ubuntu、CentOS的差异
centos yum rpm
ubuntu apt-* dpkg
(2)何添加一个新用户?
useradd
password
(3)什么是shell?
Shell是系统的用户界面,提供了用户与内核进行交互的一种接口。实际上shell就是一个命令解释器,它接受用户输入的命令后进行解释并把他们送到内核去执行。
(4)ls 命令的各种选项
- -a 显示所有文件及目录(包括隐藏文件)
- -l 除文件名称外,亦将文件形态、权限、拥有者、文件大小等资讯详细列出
- -r 将文件以相反次序显示(原定依英文字母次序)
- -t 将文件依建立时间之先后次序列出
- -A 同-a,但不列出(当前目录)以及(父目录)
- -F 在列出的文件名称后加一字符;例如可执行档则加“*”,目录则加“/”
- -R 若目录下有文件,则以下文件皆依序列出(递归)
(5)建立、复制、删除目录
mkdir dir
cp dir ./dir1
rmdir dir#删除空目录
(6)chmod命令,修改权限
chmod ugo+rwx filename
(7)grep 与正则表达式
文件或文本筛选
- -v 显示不匹配的行
- -n 显示行号
正则表达式
- ^行开头
- $行末尾
- .表示任意一个字符
- *和0或任意多个前驱字符进行匹配
- []与其中一个字符进行匹配
- [a-z]与范围内的一个字符进行匹配
- [^a-z]与不在范围内的一个字符进行匹配
(8)sort命令
对指定的文件内容按照字母顺序进行排序
- -n 对指定的内容按照数字大小进行排序。
eg:
sort -t : -k 3 -n user.txt
#-t : 代表设置分隔符为:
#-k 3 代表用设置后分隔的第三列进行排序
#-n 代表按照数字排序
(9)wc命令,管道的使用
统计文件的字节数、单词数、行数
-w #统计单词数
-c #统计字节数
-l #统计行数
-m #统计字符数
-L #显示最长行的长度
管道:前一个的输出作为后一个的输入。
(10)pwd和PWD
查看当前目录地址
(11)各种压缩命令,特别是tar命令
tar将文件进行归档提取压缩解压等操作
- c:创建归档
- x:展开归档
- z:调用gzip对归档进行压缩/解压
- j:调用bzip2对归档进行压缩/解压
- v:显示冗余信息
- f:指定归档文件名
(12)find 命令
搜索文件,如果未指定任何参数,则在当前目录下查找子目录,并将结果显示
find [目录][选项][动作]
- -name 指定文件名,可以使用通配符
- -type 按类型进行查找
动作
- -exec将查找的的目标进行进一步处理,exec后跟随处理命令,命令通过{}引用被找的文件,而且命令必须以";"结束,-exec的命令回代替find命令原来的输出内容。
find ./ -type f -exec ls -l {} \;#查找当前目录下的所有普通文件并调用ls -l进行显示
(13)mv命令,移动与改名
略
(14)ln与ln -s命令,符号链接文件与硬链接文件的区别?
- 区别:软链接只是指向原文件的名字。创建软连接时创建一个文件,文件的内容就是原来文件的地址,如果删除原文件,则找不到软链接实际连接的文件了。
- 相反,创建硬链接时创建一个inode,inode指向原文件,文件的连接数加一。
(15)head tail cat more
cat :用于连接文件并在标准输出上输出
more:用于分页显示 (空格下一行,b返回上一页)
less:可以随意浏览文件,支持翻页搜索,支持向上翻页和向下翻页,more增强版
head:用于显示从问及那开头的内容,默认显示前10 行
tail:显示文件尾向前的内容
(16)bc计算,与echo命令搭配,如何做计算?如何做小游戏或者浮点数的计算?
数字运算器:一般bash只能计算整数,但是可以通过这个命令计算浮点数。
bc
1.2345*6
scale=3
4/87
sqrt(10000)
#管道
echo "scale=2;3/4"|bc
(17)ps -l命令
查看进程的所有信息
ps -l#采用详细的格式来显示程序状况
(18)who free命令
显示当前在线的用户
free命令:显示系统内存使用量情况
(19)kill命令以及kill函数(C语言)
kill命令
kill [信号值] pid
常用信号值
- 1:重新加载进程
- 9:杀死一个进程
- 15:正常停止一个进程
(20)大写的PWD、PATH、HOME、USER分别表示什么含义?
- $PWD 保存用户当前在文件系统的位置
- $PATH 定义查找命令的目录列表,目录名用冒号隔开
- $HOME 用户的注册目录(用户主目录)
- $USER 保存当前的用户名
- $SHELL设置当前用户的shell类型
(21)shell元字符?、[]、{}的使用
shell 元字符
> prog > file 将标准输出重定向到文件
>> prog >> file 将标准输出附加到文件
< prog < file 从文件file中获取标准输入
| p1 | p2 将p1的标准输出作为p2的标准输入
<<string Here Document: 标准输入从Here Document读入,直到出现string
* 匹配文件名中的零个或多个字符
? 匹配文件名中的任何单个字符
{abc} 匹配文件名中abc范围内的任何字符,如0-9或a-z都是合法的
; 命令结束符,例如p1; p2表示先执行p1,再运行p2
& 命令结束符,与 ; 类似,但不等p1结束
`...` 运行...中的命令,输出的结果代替`...`
(...) 在子shell中执行...中的命令
{...} 在当前shell中执行...中的命令(很少使用)
$1,$2等 $0...$9 代表shell文件的参数
$变量 shell变量的值
${变量} 变量的值,为避免在文本连接时混淆
/ /c 将 c 字符作为字符,但 / 后面加换行符无效
'...' 作为文本,不作任何替换
"..." 在 ... 中的$、`...` 和 / 得到替换后,将 ... 作为文本
# 表示注释
变量=值 为变量赋值
p1&&p2 运行p1;若成功,再运行p2
p1||p2 运行p1;若不成功,再运行p2
_____________________________________________________________________
Shell 内部变量
$# 参数个数 ,从0开始计数
$* shell的所有参数
$@ 类似$*,具体请参看文章http://bbs.chinaunix.net/viewthread.php?tid=218853&extra=&page=7
$- shell用的选择项
$? 上次执行的命令的返回值
$$ shell的进程标识符
$! 用&启动的最后一个命令的进程标识符
$HOME cd命令的缺省参数
$IFS 参数分隔词的字符表
$MAIL 信件文件,当其改变时给出信息you have mail ... 没用过这个^_^
$PATH 搜索命令的目录表
$PS1 提示符串,缺省为$
而本题答案为
? #匹配一个字符
[] #里面填写条件测试
{} #里面语句放在当前shell中执行
() #放在子shell中执行 ,不影响当前shell
(22)重定向> >> <,命令的后台执行,顺序执行分别用什么?
- >> 将一个文件的内容重定向到另一个文件的末尾 cat lxlinux >> alvin
- > 将输出重定向到另一个文件 ls > list.txt
- < 将输入信息重定向至命令中作为参数使用
- 2> 错误信息默认进入stderr流中,使用2>可以对其进行重定向 ls /nope 2>output.log
- 在linux文件系统中,null,也存在一个文件相对应,放在/dev下 /dev/null并不保存数据,写入其中的数据最终都会丢失,所以可以将不需要的数据送入/dev/null中。
后台执行:cmd(命令)& :后台运行,关掉终端会停止运行
nohup cmd(命令) &:后台运行,关掉终端不会停止运行
ctrl +z将正在前台执行的命令放到后台,且让命令处于暂停状态。
fg将后台命令放回前台运行
顺序执行:
cmd1 && cmd2
命令1执行成功再执行命令2
cmd1||cmd2
命令1执行失败再执行命令2
$sh test.sh ||(echo "failed";exit;shutdown)
执行test.sh脚本,如果失败了,就输出“failed”,然后退出脚本,最后关机
$sort file1.txt > file1_sorted.txt && (echo "success";cp file1_sorted.txt /tmp/log/file1_sorted.txt;exit)
对file1.txt排序并输出到file1_sorted.txt中,如果成功了,将file1_sorted.txt拷贝到/tmp/log中,最后退出
(23)vim的各种命令格式、末行模式的基本操作
第二章
(1)bash脚本的第一行含义
写作
#! /bin/bash
用来向内核说明由哪个类型的shell执行该脚本
之后就是程序主体了
(2)bash脚本中,$0,$1,$#,$*,$?的含义
$0 #命令名称/文件名称
$1 #第一个参数的名称
$# #参数个数
$* #全部参数
$? #上一条命令的返回值
(3)shell编程例题
知道(),{},[],``,(())的使用方法。
(4)echo "$i"与echo '$i’的执行结果的区别。
#第一个输出i的值
#第二个输出$i
单引号中的内容被视为字符串,无视特殊字符。
双引号中不会无视特殊字符,如果要输出特殊字符要用\来转义。
反引号是用来包含命令字符串的,反引号中的命令会先被执行,将执行结果返回。
(5)read命令 read $xyz是否正确
不正确 $xyz不是一个有效的标识符
(6)牢固掌握if语句的用法
if []
then
elif []
then
else
fi
(7)shell下如何做字符串拼接
# !/bin/bash
str01="1""2"
echo ${str01}
str02="1"'2'
ehco ${str02}
str03=${str01}${str02}
echo ${str03}
str04=${str01}"end"${str02}
echo ${str04}
str05="${str01}${str02}"
echo ${str05}
(8)如何判断一个变量是文件还是目录 -e -s的含义
- -f 普通文件
- -d 目录
- -e 文件存在
- -s 文件大小非零
(9)字符串、表达式的比较
(13)数组,a=(one two …)是什么含义
(14)斐波那契数列的构造及其求和
注:下列内容中,系统调用与函数在说法上没有加以区分。
第三章
(1)gcc -c 的含义
只编译,不链接,生成文件(一种中间文件或者临时文件)
(2)gcc编译过程包括哪些步骤,其中的链接步骤指的是什么?gcc -o
预处理、编译、汇编、链接
将汇编产生的obj文件,系统库的obj文件、库文件链接起来,最终生成可执行程序。
gcc编译:预处理-E,入头文件,编译-S,检查并转汇编,汇编-c,转二进制,链接-o,链接库文件
编译参数使用:
gcc -E -o hello.i hello.c -o及其文件需要指定,生成hello.i
gcc -S hello.c -o及其文件无需指定,生成hello.s
gcc -c hello.c -o及其文件无需指定,生成hello.o
gcc -o hello hello.c 生成hello可执行
(3)静态库与共享库的不同之处是什么?
共享库——动态链接库
- 静态库:程序编译时进行链接
- 动态库:程序运行时进行链接
(4)make命令的功能、好处?makefile 、Makefile的作用,基本结构?
make工程管理器时一个“自动编译管理器”,“自动”指它能够根据文件时间戳自动发现更新过的文件而减少编译的工作量
makefile文件——描述系统中各个模块之间的依赖关系
makefile文件通常包括:
需要由make工具创建的目标(target),通常是目标文件或可执行文件
创建目标所依赖的文件
创建每个目标时需要运行的命令
其它要执行的动作(如clean)
第四章
(1)时间函数(asctime、localtime、time)的使用方法
char *asctime(const struct tm* tp)
//将指定使劲啊转换为字符形式的时间,长度大概26个字母
struct tm*localtime(const time_t*timep)
//将时间转换为当地人更人性化的时间
time_t time(time_t *t)
//系统调用,返回自1970.1.1午夜以来流失的秒数
(2)tm结构的基本属性
struct tm{
int tm_sec;//Seconds
int tm_min;//Minutes
int tm_hour;//Hours
int tm_mday;//Day
int tm_mon;//Month
int tm_year;//Year-1900
int tm_wday;//Day of week
int tm_yday;//Days in year
int tm_isdst;//夏时令
}
(3)如何在C语言中输出当前的时间?(不适用system或者exec函数族)
#include <stdio.h>
#include <string.h>
#include <time.h>
int main(void)
{
struct tm t; //tm结构指针
time_t now; //声明time_t类型变量
time(&now); //获取系统日期和时间
localtime_s(&t, &now); //获取当地日期和时间
//格式化输出本地时间
printf("年:%d\n", t.tm_year + 1900);
printf("月:%d\n", t.tm_mon + 1);
printf("日:%d\n", t.tm_mday);
printf("周:%d\n", t.tm_wday);
printf("一年中:%d\n", t.tm_yday);
printf("时:%d\n", t.tm_hour);
printf("分:%d\n", t.tm_min);
printf("秒:%d\n", t.tm_sec);
printf("夏令时:%d\n", t.tm_isdst);
//getchar();
return 0;
}
(4)什么是用户空间、什么是内核空间
内核空间是内核代码运行的地方,用户空间是用户代码运行的地方。
(5)getenv与env命令
char*getenv(char*name);//获得名称为name的环境变量的值
int putenv(char*str);//添加变量或修改变量值,str格式:name=value
int setenv(char*name,char*value,int overwrite);//若name不存在则添加,若存在且overwrite为1则用value值更新原值,若overwrite为0则忽略
int unsetenv(char *name);//删除指定环境变量
extern char**environ
//所有环境变量
第五章
(1)什么是系统调用、什么是函数?
系统调用:是操作系统为用户态运行的进程和硬件设备(如CPU、磁盘、打印机等)进行交互提供的一组接口;是操作系统留给用户程序的一个接口。系统调用直接运行在内核空间。系统调用面向硬件,不带缓冲。系统调用是操作系统相关的,因此一般没有跨操作系统的可移植性。
库函数调用:面向应用开发,相当于应用程序的API。它对系统调用进行了封装,库函数的优势:第一:双缓冲技术的实现。第二,可移植性。第三,弥补了底层调用本身的一些性能方面的缺陷。库函数调用运行在用户空间
(2)system 函数与exec函数族的使用方法、区别
int system(char*cmdstr);
//产生一个子进程,调用/bin/sh -c来执行cmdstr指定的内容,调用失败返回-1,成功返回0
(3)chmod函数
#include<sys/types.h>
#include<sys/stat.h>
int chmod(char *path,mode_t mode);
//修改path指定的文件的权限,注意当前用户的身份
//mode可以表示为一串八进制数字
//eg:所有者读写,其他人读
S_IRUSR | 所有者读权限 | S_IXGRP | 组成员执行权限 |
---|---|---|---|
S_IWUSR | 所有者写权限 | S_IROTH | 其他人读权限 |
S_IXUSR | 所有者执行权限 | S_IWOTH | 其他人写权限 |
S_IRGRP | 组成员读权限 | S_IXOTH | 其他人执行权限 |
S_IWGRP | 组成员写权限 |
(4)umask函数的作用,umask命令的使用方法
mode_t umask(mode_t cmask);
//修改当前进程环境的权限掩码为cmask:八进制,同上
//返回修改之前的掩码
(5)stat结构体与stat函数、stat命令的联系,各自的功能
#include<sys/stat.h>
#include<unistd.h>
struct stat{
dev_t st_dev;//文件的设备编号
ino_t st_ino;//结点
mode_t st_mode;//文件的类型和存取的权限
nlink_t st_nlink;//连到该文件的硬链接数目,刚建立的文件值为1
uid_t st_uid;//用户ID
gid_t st_gid;//组ID
dev_t st_rdev;//(设备类型)若此文件为设备文件,则为其设备编号
off_t st_size;//文件字节数(文件大小)
unsigned long st_blksize;//块大小(文件系统的I/O缓冲区大小)
unsigned long st_blocks;//块数
time_t st_atime;//最后一次访问时间
time_t st_mtime;//最后一次修改时间
time_t st_ctime;//最后一次改变时间
};
int fstat(int fd, struct stat *buf);
//获取指定文件描述符文件的属性信息,并填充到buf
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);
//获取指定文件文件的属性信息,并填充到buf
//若文件为符号链接,stat返回的是该链接指向的文件的信息,而lstat返回的是符号链接的属性信息
//文件判断宏
//若为对应文件返回1
int S_ISREG(st_mode); 常规文件
int S_ISDIR(st_mode); 目录
int S_ISBLK(st_mode); 块设备
int S_ISCHR(st_mode); 字符设备
int S_ISSOCK(st_mode); 套接字
int S_ISFIFO(st_mode); 命名管道
int S_ISLNK(st_mode); 符号链接
//文件权限判断
//拥有权限返回1
st_mode & 权限码
//eg:
//判断所有者读权限
st_mode & S_IRUSR
(6)如何根据stat结构体过的文件的类型、权限等信息?
略
(7)文件描述符与文件指针的区别,各自的应用环境
文件指针:指向进程用户区的一个被称为FILE结构的数据结构。
FILE结构包括缓冲区和文件描述符,文件描述符是问及那描述符表的一个索引,也就是说C语言的文件指针是Linux系统中对文件描述符的一种封装
文件描述符:Linux系统中打开文件就会获得文件描述符,它是个很小的正整数。
(8)open、close、read、write 要非常熟悉。读文件、读键盘、输出到屏幕、输出到文件操作要熟悉。
(9)open文件时如果采用O_NONBLOCK方式,则后续的效果时什么样的?
如果路径名指向 FIFO/块文件/字符文件,则把文件的打开和后继 I/O设置为非阻塞模式(nonblocking mode)
(10)open文件时,O_TRUNC、O_WRONLY是什么方式?
O_TRUNC:清空原有内容
O_WRONLY:以只写方式打开文件
(11)如何利用C语言实现文件的复制?如何编写属于自己的命令程序,mycp?
(12)opendir、readdir、closedir是用来做什么的?
opendir:打开目录
readdir:
closedir:关闭目录
(13)如何将指定目录下的文件或目录的详细信息(名称、类型、大小、修改时间等)列举出来
第六章
(1)如何获得进程的PID 、PPID?
getpid();getppid();
(2)熟练掌握fork函数的用法
int pid=fork();
(3)什么是僵尸进程、什么是孤儿进程,由谁来回收
- 僵尸进程:一个已经中止运行、但其父进程尚未对其进行善后处理(释放其PCB块)的进程
- 孤儿进程:使用fork创建的子进程,父进程已经结束,子进程还在运行,这种进程为孤儿进程。这种进程很快会被init进程(PID=1)收养。
(4)sleep函数的作用?
让进程休眠一段时间
(5)如何避免僵尸进程,wait函数,waitpid函数的多种用法
让僵尸进程的父进程来回收,父进程每隔一段时间来查询子进程是否结束并回收,调用wait()或者waitpid()通知内核释放僵尸进程
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#include<sys/wait.h>
int main(){
pid_t pid=fork();
int n=0;
char *s=null;
if(pid<0){
perror("fork create failed!\n");
}else if(pid>0){
n=1;
s="this is the parent process!\n";
}else {
n=10;
s="this is the parent process!\n";
}
for(int i=0;i<n;i++){
printf("%s\n",s);
if(pid>0){
printf("I am waiting for you , my child\n");
wait(NULL);
}
sleep(1);
}
printf("%s bye\n",s);
return 0;
}
采用信号SIGCHLD通知处理,并在信号处理程序中调用wait函数。
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<signal.h>
void signal_wait(int isig){
wait(NULL);
printf("child is cleaned\n");
}
int main(){
pid_t pid=fork();
char*s =NULL;
if(signal(SIGCHLD,signal_wait)==SIG_ERR){
perror("install signal_wait");
}
if(pid<0){
perror("fork create");
}else if(pid>0){
sleep(1);
s="this is parent process";
}else{
s="this is child process";
}
printf("%s bye",s);
return 0;
}
(6)如何产生多个进程,而不发生僵尸进程,进程号之间彼此有什么关联?
(7)WIFEXITED、WEXITSTATUS两个宏是用来做什么的?
(8)什么是SIGCHILD信号有什么作用?
在子进程结束时向父进程发出。只有在父进程运行wait函数时才会被捕捉。
(9)父进程如何给其子进程发送信号,通过什么函数?kill函数与raise函数的区别是什么?
通过pipe管道函数
kill函数是发送信号给指定的进程
raise函数是发送信号给当前进程
(10)守护进程的特点是什么?如何产生一个守护进程?产生守护进程的每个步骤的作用分别是什么?
运行在后台,独立于控制台并周期性的执行某种任务或等待处理某些发生的事件。
- 创建子进程,中止父进程:造成已经运行完的假象
- 在子进程中创建新会话:使进程完全独立出来,从而脱离所有其它进程控制。
- 改变工作目录:防止当前目录所在文件系统卸载
- 重设文件创建掩码:子进程继承父进程文件创建掩码,产生限制,故将其重设为0可以增强守护进程灵活性。
- 关闭文件描述符:子进程可能从父进程那里继承一些已经打开了的文件,这些文件可能永远不会被子进程读或者写,但一样消耗资源。
(11)什么是进程组、什么是会话组?
进程组为一个或多个进程的集合,有进程组号PGID
会话为一个或多个进程组的集合,有SID,有一个前台进程组和多个后台
(12)守护进程是孤儿进程吗?
是,一个由init继承的孤儿进程。
(13)如何编写简单的守护进程?例如周期性地向指定文件中写入当前的最新时间、如何监督检查指定文件是否被修改过?
#include<unistd.h>
#include<signal.h>
#include<sys/param.h>
#include<sys/types.h>
#include<sys/stat.h>
void init_daemon(void ){
pid_t child1,child2;
int i;
child1=fork();
if(child1>0){
exit(0);
}else if(child1<0){
perror("创建失败");
exit(1);
}
setsid();//在子进程中创建新会话
chdir("/tmp");//改变工作目录到"/tmp"
umask(0);//重设文件创建掩码
for(i=0;i<NOFILE;i++)close(i);//关闭文件描述符
return ;
}
第七章
(1)进程间通信的几种方式是什么?
- 信号:一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
- 管道:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有沁园关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
- 命名管道FIFO:管道是一种半双工的通信方式,但是它允许无亲缘关系进程间的通信。
- 消息队列:消息队列是由消息的链表存放在内核中,并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等特点
- 共享存储:共享内存就是映射一段能被其它进程所访问的内存,这段内存由一个进程创建,但多个进程都可以访问。共享内存是最快的IPC方式,它是针对其它进程间通信方式运行效率低而专门设计的,它往往与其它通信机制(如信号量)配合使用,来实现进程间的同步和通信。
- 信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其它进程也访问该资源。因此,它主要作为进程间以及同一进程内不同线程之间的同步手段
- 套接字:套接字也是一种进程间通信机制,与其它通信机制不同的时,它可用于不同及其间的进程通信。
(2)用户进程对于信号响应的方式有哪些?如何编程实现?
- 执行默认操作:Linux对每种信号都规定了默认操作
- 捕捉信号:定义信号处理函数,当信号发生时,执行相应的处理函数
- 忽略信号:当不希望接收到的信号对进程的执行产生影响,而让进程继续进行时,可以忽略该信号,即不对信号进行任何处理。
(3)alarm 函数、signal函数的用法?
alarm:定时器时间到,向进程发送SIGALARM信号
signal:捕捉信号SIGNT、SIG_IGN、SIG_DFL或SIGQUIT时执行信号处理函数。
//告诉内核在seconds秒轴给当前进程发SIGALARM信号,该信号默认中止当前进程
#include<unistd.h>
#include<stdio.h>
#include<stdio.h>
int main(){
int counter;
double j;
alarm(10);
for(counter=0;1;++counter){
printf("正在计数中:%d\n",counter);
for(j=0;j<1000000;j+=0.1);
}
return 0;
}
(4)当前进程如何在收到某一特定的信号(例如SIGINT)后,不执行默认的操作,转而执行自定义的操作?
void func();
int main(){
(void)signal(SIGINT,func);//收到SIGINT信号后转而执行func函数
}
(5)SIGKILL与SIGSTOP的特殊性在哪里?SIGINT、SIGQUIT、SIGTERM的共同点是什么?
SIGKILL和SIGSTOP信号时无法捕捉和忽略的,两者都是为了使系统管理员能在任何时间中断或结束某一特定的进程而设置的。
(6)什么是管道?什么是匿名管道、什么是命名管道,各自的应用场景是什么?
管道允许在进程之间按照先进先出的方式传送数据,使进程间通信的以中常见的方式。
匿名管道:是半双工的,数据只能向一个方向流动;需要通信的时候,需要建立起两个管道;只能用于具有亲缘关系的父子进程或者兄弟进程之间通信。
命名管道:其与匿名管道的不同之处在于它提供以个路径名与之关联,以FIFO的文件形式存在于文件系统中,即使通过FIFO不相关的进程也能交换数据。
(7)如何利用pipe系统调用实现父子进程的管道通信?
- 父进程调用pipe函数开辟管道,得到两个文件描述符指向管道的两端。
- 父进程调用fork函数创建子进程,那么子进程也有两个文件描述符指向同一管道。
- 父进程关闭管道读取端,子进程关闭管道写入端。父进程可以往管道里写,子进程可以往管道里面读,管道是用环形队列实现的,数据从写入端流入,从读取端流出,这样就实现了进程间通信。
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<string.h>
int main(){
pid_t result;
int r_num;
int pipe_fd[2];
char buf_r[100],buf_w[100];
memset(buf_r,0,sizeof buf_r);
if(pipe(pipe_fd)<0){
printf("创建管道失败");
return -1;
}
result=fork();
if(result<0){
perror("创建子进程失败");
exit(0);
}
else if(result==0){
close(pipe_fd[1]);
if((r_num=read(pipe_fd[0],buf_r,100))>0)
printf("子进程从管道读取%d个字符,读取的字符串是:%s\n",r_num,buf_r);
close(pipe_fd[0]);
exit(0);
}else{
close(pipe_fd[0]);
printf("请从键盘输入写入管道的字符串\n");
scanf("%s",buf_w);
if(write(pipe_fd[1],buf_w,strlen(buf_w))!=-1)
printf("父进程向管道写入:%s\n",buf_w);
close(pipe_fd[1]);
waitpid(result,NULL,0);
exit(0);
}
}
(8)命名管道文件的类型是以什么开头的?
- d 文件夹
- l 链接文件
- b 块设备
- c 字符设备
- p 命名管道