命名管道:(由于匿名管道(没有名字,没有路径)通信只能具有亲缘关系的进程之间能,大大限制了进程间通信的能力)
命名管道的特点:
1、可以使用不同进程(无论是否有亲缘关系的进程)通信
2、是一个特殊文件:文件名与路径(文件系统中),是一个FIFO的文件(没有lssek)
3、普通在读写方面没有阻塞,而FIFO文件却与普通不同在读写方面:
进程读:
1、若该FIFO管道是阻塞打开,且FIFO文件中没有内容则阻塞等待,直有到信息写入。
2、若该FIFO管道是非阻塞打开,无论FIFO中是否有内容,都不会阻塞等待。
进程写:
1、非阻塞打开文件,无论读进程是否读取了,都会立即执行
2、阻塞打开文件,如果读进程不读取完成,则写进程一直等待
注:fifo默认是阻塞文件。
API:创建一个管道文件:
int mkfifo(const char *pathname, mode_t mode);
返回值:0成功 -1失败 错误码在errno中
pathname:路径
mode:权限
阻塞模式创建命名管道文件 ./info 对管道文件进行写入数据 .
#include
#include
#include
#include
#include
#include
#include
//系统错误
#include
using namespace std;
int main()//写进程
{
//1第一步:创建管道named文件
if(mkfifo("./info",0644)<0)
{
if(EEXIST!=errno)
{
perror("mkfifo fail");
return -1;
}
}
//1打开写入:以只读和非阻塞打开
int fd=open("./info",O_WRONLY);
//2操作
char msg[100]="I Love You!#Do you love me?";
cout<
新建一个文件 , 用于读取命名管道里面的数据 ./info .
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
//打开
int fd=open("./info",O_RDONLY);
if(fd<0)
{
perror("open fail\n");
return -1;
}
//读取
char ch;
while(read(fd,&ch,1)>0)
{
if(ch=='#')
cout<
非阻塞模式打开文件 O_NONBLOCK 方式打开 .
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
//打开
int fd=open("./info",O_RDONLY|O_NONBLOCK);
if(fd<0)
{
perror("open fail\n");
return -1;
}
//读取
char ch;
while(read(fd,&ch,1)>0)
{
if(ch=='#')
cout<
信号:(system IPC:UNIX)是比较古老的进程间通信的一种方法。主要是向另外一个进程发出通知。
1、信号:系统给每一个信号都取了一个编号:
shell: Kill -l
31号信号之前代表不靠信号
34信号之后可靠(链式结构)
shell: man 7 signal (具体的说明)
1) SIGHUP 停止进程 终端退出时
2) SIGINT 停止进程 Ctrl+C组合键,发出
9) SIGKILL 停止进程 用户退出进程
14) SIGALRM 时钟闹钟
10) SIGUSER1 12)SIGUSER2 用户自定义信号
17) SIGCHLD 子进程退出,子进程发送给信息给父进程
信号的处理方式:
1、系统默认处理SIG_DFL
2、用户自处理
3、忽略;SIG_IGN
产生一个信号:
1、硬件产生: ctrl+c 硬件产生一个信号 结束
ctrl+/ 硬件产生一个信号 结束(产生一个core文件)
2、系统产生:
子进程退出,给父进程发送信号
3、用户调用内核API来产生:
kill raise alarm pause
int kill(pid_t pid, int sig);
pid:进程的ID sig信号标识
int raise(int sig);
unsigned int alarm(unsigned int seconds);
注:只允许定义一个闹钟,多个会被最新的替换
pause() 等待任意一个信号到来就唤醒。
注:信号处理是异步方式
(同步与异步)
处理信息的步骤:
1、注册:信号+处理方式
2、信号的产生
拓展:
前端进程:进程在终端上运行
后台进程:脱离终端,在后参运行。 可执行文件 &
信号集 :
使用信号集函数处理一组信号,这些信号按照调用的先后次序分为如下几类:
1、创建信号集:
2、登记信号:决定进程如何处理信号
3、信号的处理与检测:
创建信号集
int sigemptyset(sigset_t *set);//清空信号集
int sigfillset(sigset_t *set); //填满
int sigaddset(sigset_t *set, int signum);//增加某个信号
int sigdelset(sigset_t *set, int signum);//删除某个信号
int sigismember(const sigset_t *set, int signum);//查询信号是否在该信号集中
创建信号集 , signal(SIGINT,sigfun); ---->用户自处理
signal(SIGINT,SIG_DFL); ---->系统默认处理
设置信号集的功能:
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
how:指定信号集的的
set:信号集
olds:把回之前的信号集
指定信号集的动作:
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
act:将进程的信号集修改
old:返回修改前的信号集
#include
#include
using namespace std;
//信号用户自处理
void sigfun(int sig)
{
//用户发送SIGINT(Ctrl+C)
if(SIGINT==sig)
{
cout<<"用户想干掉我"<
闹钟的信号 .
#include
#include
#include
using namespace std;
void sigfun(int sig)
{
if(sig==SIGALRM)
{
cout<<"闹钟响啦,休息一下"<
闹钟信号 .
#include
#include
#include
#include
using namespace std;
void sigfun(int sig)
{
if(SIGALRM==sig)
{
cout<<"闹钟响了"<
信号集的实现 .
#include
#include
#include
using namespace std;
void sigfun(int sig)
{
if(SIGINT==sig)
{
cout<<"如果你想退出进程,请按Ctrl+\\"<