信号:软中断模拟机制,类似于通知
管道:可以进行数据传输,具有单向导通性以及阻塞
共享内存:多个进程共享一块数据,可以随时读取以及更改
信号量集:同步保护资源
消息队列:最符合通信思想,单纯收发数据
套接字:用于网络通信
多任务的操作系统
资源的共享
通知事件
进程控制
数据的传输
他的特点是单向通信。遵循先进先出规则
首先他有两个端,一端用户写数据,一端用户读数据
写端只能用来写数据,不能用来读数据
读端只能用来读数据,不能用来写数据
并且会发生写阻塞和读阻塞,只有读端和写端同时存在才有意义
函数的功能:创建一个无名管道 (无名管道是用于父子间进行通信的)
函数的头文件:#include
函数的原型:int pipe(int pipefd);
函数的参数:int pipefd:用来存放读端和写端的文件描述符的
pipefd[0]:读端
pipefd[1]:写端
函数的返回值:成功返回 0 失败返回 -1
无名管道的特点:
① 只能用于有亲缘关系的进程间通讯,并不会在进程空间产生一个实实在在的管道文件
② 数据读出之后就不存在管道中
③ 创建无名管道的时候 会直接得到两个文件描述符。有了文件描述符就可以向管道中读取或者是写入内容
④ 无名管道有固定的读端和写端。假如管道里没有内容 读取的时候就会阻塞;假如管道写满数据 再往里写数据 也会阻塞 最多可以写入 65536 个字节
无名管道使用注意事项:
① 必须在 fork 函数之前调用 pipe 函数,否则子进程将不会继承文件描述符
② 只有在读端存在的时候,向管道写入内容才有意义
③ 管道里的数据 假如一直不读取 写满数据就会阻塞
④ 父子进程运行的先后顺序不确定,为了保证父进程先执行,可以在子进程中调用 sleep(1) 函数
1 #include2.2 有名管道 mkfifo2 #include 3 #include 4 #include 5 #include 6 pid_t pd; 7 int fd[2]; 8 int main() 9 { 10 pipe(fd); //pipe函数要在fork函数之前,保证父子进程资源相同,在一个管道中 11 pd=fork(); 12 if(pd<0) 13 { 14 perror("fork"); 15 return -1; 16 } 17 if(pd>0) 18 { 19 close(fd[0]);//关闭父进程的读 20 write(fd[1],"father space!",13);//打开父进程的写,要写入的内容,要写入内容的大小 21 printf("pipe num1:%dn",pipe(&fd[1]));//打印pipe函数写的返回值,看是否写入成功 22 printf("this is father test!n"); 23 printf("current1 pid:%dn",getpid());//这是父进程中,当前的父进程号 24 } 25 else if(pd==0) 26 { 27 char buf[100];//创建一个字符数组,用来存放读取到的内容 28 close(fd[1]);//关闭子进程的写 29 read(fd[0],buf,15);//打开子进程的读,并将读取到的内容放在buff里,要读取内容的大小 30 printf("pipe num2:%dn",pipe(&fd[0]));//打印pipe函数读的返回值,看是否读取成功 31 printf("son space welcome:%sn",buf);//子进程获取到父进程中的内容,并打印出来 32 printf("current2 pid:%dn",getpid());//这是子进程中,当前的子进程号 33 } 34 return 0; 35 }//输出: pipe num1:0 this is father test! current1 pid:3108 pipe num2:0 son space welcome:father space! current2 pid:3109
函数功能:创建一个有名管道 (有名管道是可以用于任意进程间进行通信)
函数的头文件:#include
#include
函数的原型:int mkfifo(const char *pathname, mode_t mode);
函数的参数:const char *pathname:要创建的管道的名字(带路径)
mode_t mode:创建管道的时候给的权限
函数的返回值:成功返回 0 失败返回 -1
特点:
会创建一个真正存在的管道文件,用于任意两个进程间通讯
注意:
在有名管道里 读端只能以只读的方式打开文件
写端只能以只写的方式打开文件
读端和写端在不同的终端打开,如果有名管道文件已经存在,则需要注释掉创建有名管道的语句。
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 int main() //这里是写端 8 { 9 int ret,fd; 10 // ret=mkfifo("./mktest",0777);//创建一个有名管道文件,并赋予它指定的权限,如果已存在,则需注释掉,否则显示文件已存在 11 if(ret<0)//如果返回值小于零,说明有名管道文件创建失败 12 { 13 perror("mkfifo"); 14 return -1; 15 } 16 if(!access("./mktest",F_OK))//access函数判断文件是否存在,如果存在则返回零,所以要取反 17 { 18 fd=open("./mktest",O_WRONLY);//在写端以只写的方式打开有名管道文件 19 write(fd,"hello world!",12);//要写入的内容,及写入内容的大小 20 } 21 close(fd); 22 return 0; 23 }
1 #include2.3 删除文件 unlink2 #include 3 #include 4 #include 5 #include 6 #include 7 int main() //这里是读端 8 { 9 char buf[20]; 10 int ret,fd; 11 // ret=mkfifo("./mktest",0777);//创建一个有名管道文件,并赋予它指定的权限,如果已存在,则需注释掉,否则显示文件已存在 12 if(ret<0) 13 { 14 perror("mkfifo"); 15 return -1; 16 } 17 if(!access("./mktest",F_OK)) 18 { 19 fd=open("./mktest",O_RDONLY);//在读端以只读的方式打开有名管道文件 20 read(fd,buf,12);//要打开的文件描述符为0,读取到的内容存放在buff里,读取到的字节数 21 printf("buf:%sn",buf);//打印出读取到的内容 22 } 23 close(fd); 24 return 0; 25 }
函数功能:删除文件(删除一个有名管道文件)(目录文件无法删除)
函数的头文件:#include
函数的原型:int unlink(const char *pathname);
函数的参数:const char *pathname:要删除的文件的名字(带路径)
函数的返回值:成功返回 0 失败返回 -1
1 #include2 #include 3 int main() 4 { 5 unlink("./mktest");//要删除的管道文件名 6 return 0; 7 }
普通文件和有名管道文件的区别:
①要读取有名管道的内容 必须以O_RDONLY方式打开
②要写有名管道时 必须以O_WRONLY方式打开
③有名管道里的内容 读取一次之后 就没有了,普通文件读完之后 内容还在
信号:是用来通知进程要去干什么。信号就是内核里一个通知的机制,这个机制是一个软中断
中断:就是打断当前正在执行的事情 转而去做另外的事情,另外的事情执行完之后 再回过头来执行之前未执行完的事情。
先要保护现场(压栈) 另外的事情做完之后 再回过来
做我没有做完的事 在做这个事之前要做恢复现场(出栈)
信号产生的时机:任意时间
信号的周期
信号产生
信号在进程里注册
信号在进程里注销
信号处理函数
信号的查看:kill -l
共有 62 个信号
2) SIGINT ctrl+c 杀死进程
3) SIGQUIT ctrl+ 杀死进程
9) SIGKILL kill信号
14) SIGALRM 时钟信号
信号的相关说明
32位之前叫做不可靠信号,实时性不好 易丢失
32位之后位扩充信号,实时性较好 不易丢失
信号的产生有什么手段
在终端输入ctrl+c ctrl+ kill -9
内核在产生异常的时候也会发送一个信号
在进程里可以通过调用kill函数来给另一个进程发送信号
① kill 向指定的进程发送指定的信号 (重要)函数功能:向指定的进程发送指定的信号
函数的头文件:#include
函数的原型:int kill(pid_t pid, int sig);
函数的参数:pid_t pid:要给谁发信号(进程号)
int sig:要发送的信号(写数字[比如:2]或者信号所对应的宏[比如:SIGINT])
函数的返回值:成功返回 0 失败返回 -1
#include② raise 向进程本身发送信号#include int main() { kill(4082,2); return 0; }
函数功能:向自己发送一个指定的信号
函数的头文件:#include
函数的原型:int raise(int sig);
函数的参数:int sig:要给自己发送的信号
函数的返回值:成功返回 0 失败返回 -1
1 #include③ pause 阻塞一个进程,直到有信号过来为止2 #include 3 int main() 4 { 5 printf("hello world!n"); 6 raise(2);//向自己发送一个杀死进程的信号,2号信号 7 while(1);//死循环 8 }
函数功能:阻塞一个进程,直到捕捉到一个信号
函数的头文件:#include
函数的原型:int pause(void);
函数的参数:无
函数的返回值:-1
1 #include④ alarm 设置时间,杀死自己2 #include 3 #include 4 #include 5 int main() 6 { 7 printf("hello world!n"); 8 alarm(2); 9 pause(); 10 printf("the end!n"); 11 exit(0); 12 }
函数的功能:设置时间 时间到了之后产生一个14号信号 杀死自己
函数的头文件:#include
函数的原型:unsigned int alarm(unsigned int seconds);
函数的参数:unsigned int seconds:你要定时的秒数
函数的返回值:假如在调用这个闹钟之前已经设置了闹钟,但是设置的闹钟时间还没到 则返回上个闹钟剩余的时间 否则返回 0
1 #include⑤ signal 捕捉一个信号并做处理 (重点)2 #include 3 #include 4 #include 5 int main() 6 { 7 alarm(5); 8 sleep(2); 9 printf("alarm:%dn",alarm(5)); 10 printf("hello world!n"); 11 pause(); 12 printf("end of the test!n"); 13 }//输出: alarm:3 hello world! 闹钟
函数的功能:将信号的处理重新定义
函数的头文件:#include
函数的原型:sighandler_t signal(int signum, sighandler_t handler);
函数的参数:int signum:你要捕捉的信号
sighandler_t handler:捕捉到信号之后执行的函数
SIG_DFL:代表收到某个信号之后 按默认的处理 比如:signal(2,SIG_DFL);
SIG_IGN:忽略这个信号 比如:signal(2,SIG_IGN);
函数的返回值:成功返回 回调函数的指针 失败返回 SIG_ERR
1 #include2 #include 3 #include 4 #include 5 void myfunc(int signum) 6 { 7 printf("i get a signal is:%dn",signum); 8 } 9 int main() 10 { 11 printf("pid:%dn",getpid()); 12 signal(2,myfunc); 13 printf("end of the test!n"); 14 while(1); 15 return 0; 16 }//输出: pid:4316 end of the test! ^Ci get a signal is:2 ^退出 (核心已转储)



