Linux内核设计与实现—>进程管理
进程描述符和任务结构
进程间通讯
1.管线:
1.有名管线
特点
特性:1、可以用于不同进程间通讯,不限于必须有亲缘关系。
有名管线的使用
1、管道的创建=====》mkfifo
intmkfifo(constchar*filename,mode_tmode);
功能:通过该函数可以创建一个有名管线的设备文件下来。
参数:filename要创建的管线名称+路径mode创建的管线的文件权限。
返回值:成功0失败-1;
2、管道的打开=====》open
intopen(constchar*filename,intflag);
参数:filename要打开的有名管线文件名称
flag==》O_RDONLY只读O_WRONLY只写O_RDWR不能用。
3、管道的读写====>readwrite
读:ssize_tread(intfd,void*buff,size_tcount);
从fd中读count个字节的数据到buff中。
写:ssize_twrite(intfd,constvoid*buff,size_tcount)
从buff中取count个字节的数据写入到fd文件中。
4、管道的关掉====>close
close(fd);
5、管道的卸载====>unlinkintunlink(constchar*pathname);
功能:卸载或则删掉早已创建的有名管线文件
参数:pathname要卸载的管线文件名称+路径
返回值:成功0失败-1;
2.无名管线
特点
1、只能用于具有亲缘关系的进程间使用。
2、半双工通讯qq linux,有固定的读端和写端。
3、特殊的文件,可以支持文件IO。
4、管道的数据储存方法类似队列linux内核信号量,先进先出。
5、管道的默认容量大小是64k字节===》ulimit-a====>4k初期的大小
6、管道默认的读操作会阻塞等待,假如写操作满了的时侯也会阻塞等待。
7、管道的读端存在时侯,写管线才有意义,否则程序会退出.
无名管线的使用
1、管道的创建与打开intpipe(intfd[2]);
功能:通过该函数可以创建一个无名管线,同时打开该管线。
参数:fd[2]要操作的管线名称,有两个元素fd[0]管线的固定的读端fd[1]管线的固定的写端
返回值:成功0失败-1注意:在创建新的进程之前就应当先创建管线,然后之间的资源可以通过管线传递。
2、管道的读写
读:ssize_tread(intfd,void*buff,size_tcount);
从fd中读count个字节的数据到buff中。
写:ssize_twrite(intfd,constvoid*buff,size_tcount)
从buff中取count个字节的数据写入到fd文件中。
3、管道的关掉
close(fd[0]);
close(fd[1]);
2.讯号:
1.讯号的发送
kill函数=====》支持的讯号列表kill-l====>所有当前系统支持的默认讯号
头文件:signal.hsys/types.h
intkill(pid_tpid,intsig);
功能:给指定的pid进程发送sig讯号。
参数:pid要接收讯号的进程idsig要发送的讯号编号====》kill-l中的讯号kill-l中前32属于系统原始讯号,也叫不稳定讯号后32个属于稳定讯号。
返回值:成功0失败-1;
intraise(intsig);
功能:进程可以自己通过该函数给自己发送讯号。
参数:sig要发的讯号的编号
返回值:成功0失败-1;
闹铃函数和暂停函数
暂停函数
intpause(void)====>while(1){sleep(1);}
执行该函数后程序暂停。
闹铃函数
定时时间到了发送SIGALRM讯号给自己。
unsignedintalarm(unisgnedintsec);
指定间隔sec秒以后给自己发送讯号。
默认的SIGALRM讯号会使程序中止运行。
2.讯号的接收
三种形式:默认处理忽视处理自定义处理
1、捕获讯号和处理
void()(int);======>voidfun(intarg);
void(signal(intsignum,void(handler)(int)))(int);
signal(intsignum,test);===>test==void(handler)(int);typedefvoid(SIGNAL)(int);===>void(signal(intsignum,void(handler)(int)))(int);==SIGNALsignal(intsingnum,SIGNALhandler);
简化成:
#include
typedefvoid(*sighandler_t)(int);
sighandler_tsignal(intsignum,sighandler_thandler);
参数:
sig要处理的讯号
fun讯号的处理函数。
假如其是:
SIG_IGN表示该程序对所有的讯号做忽视处理。
SIG_DFL表示该程序对所有的讯号做默认处理,系统对这种讯号是如何处理的linux内核信号量,程序都会对该讯号如何处理。
fun表示改程序有一个反弹函数用来自定义处理。
函数可以接收讯号,并对讯号作出处理,三种处理方法。
忽视。
默认处理:
自定义处理:接收到该讯号以后,会调用自定义的反弹函数。
注意:在所有系统预制的讯号列表中linux系统介绍,9号SIGKILL和19号的SIGSTOP讯号不能被忽视处理。
事例:
//SIGABRT进程停止运行6
//SIGINT终端中断2
//SIGKILL停止进程(此讯号不能被忽视或捕获)
//SIGQUIT终端退出3
voidhandler(intnum)
printf("recvnum:%dn",num);
if(num==SIGQUIT)
//exit(0);
intmain()
if(signal(SIGINT,handler)==SIG_ERR)
perror("signalerr");//errno
exit(0);
3.讯号在进程间通讯中的缺陷:
1、不能发送大量数据,包括字符串。
2、发送的讯号必须是双方约定好的。
3、发送的讯号必须是系统预制的范围内的。
4、发送的讯号在接收方必须有自定义处理,通常用SIGUSR1SIGUSER2.其他讯号有系统涵义建议不要使用。
4.讯号和中断的区别
讯号是在软件层次上对中断的一种模拟,所以一般把它称为是软中断
讯号与中断的相像点:
(1)采用了相同的异步通讯方法;
(2)当检查出有讯号或中断恳求时,都暂停正在执行的程序而转去执行相应的处理程序;
(3)都在处理完毕后返回到原先的断点;
(4)对讯号或中断都可进行屏蔽。
讯号与中断的区别:
(1)中断有优先级,而讯号没有优先级,所有的讯号都是平等的;
(2)讯号处理程序是在用户态下运行的,而中断处理程序是在核态度下运行;
(3)中断响应是及时的,而讯号响应一般都有较大的时间延后。
3.IPC对象
0.基本概念
IPC对象包含了:共享显存、信号量、消息队列
1、ipc对象查看
ipcs-a====>查看对象信息
ipcs-q====>只查看消息队列的对象信息
ipcs-m====>只查看共享显存的对象信息
ipcs-s====>只查看讯号量的对象信息
2、ipc对象操作
ipcs-lipcs-lqipcs-lmipcs-ls===>查看对象的默认上限值
ipcrm===>删掉===》ipcrm-qmsgid====>删掉消息队列支队列id是msgid的对象
ipcrm-mshmid====>共享显存对象删掉
ipcrm-ssemid====>讯号量集对象删掉
3、基本操作流程:
key>申请或则创建IPC对象>读写数据====>卸载对象
1.key的获取
1、私有key=====>IPC_PRIVATE===0X00000000
2、测试key=====>ftok()====>指定路径+字符
3、自定义key====>0X12345678
key_tftok(constchar*pathname,intpro_id);
功能:通过该函数可以以指定的路径为基本生成一个惟一通配符。
参数:pathname任意指定一个不可卸载的目录同时要求改目录不能被删掉重建。
pro_id一个数字,或则字符,表示将该值与参数1做运算以后的值作为通配符。
返回值:成功返回惟一通配符,失败-1;
2.消息队列
0、头文件:
#include
#include
#include
1、申请消息队列;
intmsgget(key_tkey,intflag);
//功能:向内核提出申请一个消息队列对象。
//参数:
//key用户空间的通配符
//flag消息对象的访问权限,而且假如是第一次向内核提出申请,则须要添加IPC_CREAT和IPC_EXCL
//返回值:成功返回消息对象id失败-1
2、消息对象的操作:
1.发送消息:
intmsgsnd(intmsgid,void*msgp,size_tsize,intflag);
参数:msgid要发送到的消息对象id
msgp==>要发送的消息结构体=》
structmsgbuf{
longmtype;////消息的类型
charmtext[N];////消息的正文,N自定义的数据大小
};
size:要发送的消息正文的宽度,单位是字节。
flag:=0表示阻塞发送
=IPC_NOWAIT非阻塞方法发送
返回值:成功0,失败-1;
2.接收消息:
intmsgrcv(intmsgid,void*msgp,size_tsize,longtype,intflag);
参数:msgid要接收到的消息对象id
msgp====>要接收的消息结构体变量,必须事先定义一个空变量,拿来储存数据。
size====》要接收的数据宽度,通常是sizeof(msgp);
type====>要接收的消息类型
flag====》接收消息的形式,0表示阻塞接收IPC_NOWAIT非阻塞接收
返回值:成功0失败-1;
3.消息队列对象的卸载:
intmsgctl(intmsgid,intcmd,structmsgid_ds*buff);
功能:调整消息队列的属性,好多时侯拿来删掉消息队列。
参数:msgid要操作的消息队列对象id
cmd==>IPC_RMID====>删掉消息队列的宏
IPC_SET====>设置属性
IPC_STAT====》获取属性
buff====》属性结构体
返回值:成功0失败-1
3.共享显存
0、头文件
#include
1、key值得创建
同上。
2、shmget向内核申请共享显存对象
intshmget(key_tkey,intsize,intflag);
参数:key用户空间的惟一通配符
size要申请的共享显存大小
flag申请的共享显存访问权限,倘若是第一次申请,则须要IPC_CREATIPC_EXCL;
返回值:成功shmid失败-1;
3、shmat将内核申请成功的共享显存映射到本地
4.讯号量
————————————————
版权申明:本文为CSDN博主「刘仕豪」的原创文章,遵守CC4.0BY-SA版权合同,转载请附上原文出处链接及本申明。
原文链接:
本文原创地址://gulass.cn/lnhsjysxjcgl.html编辑:刘遄,审核员:暂无