1.命名管道
1.1,命名管道的创建
命令创建命名管道:mkfifo+命名管道的文件名
函数创建:int mkfifo(const char *pathname,mode_t mode);
参数:pathname:要创建的命名管道文件的路径以及文件名
mode:命名管道文件的权限,八进制数组(例如0644)0是八进制数的起手式
特点:升级了匿名管道,支持不同进程间通信,不再依赖亲缘关系.
命令创建和函数创建都是生成一个文件,这个文件就能代表内核里的缓冲区.
特性:读也是将管道的内容拿走了,如果读完之后也会进入阻塞状态
代码验证:
生成代表管道的文件
写进去的代码
#include<stdio.h>
2 #include<unistd.h>
3 #include<fcntl.h>
4 #include<string.h>
5 int main()
6 {
7 int fd=open("../fifo",O_WRONLY);
8 if(fd<0)
9 {
10 return 0;
11 }
12 char arr[]="Hello,World";
13 write(fd,arr,strlen(arr));
14 sleep(1);
15 close(fd);
16 return 0;
17 }
注意:这个函数单独运行之后虽然函数内部没有死循环,但是并不会退出
把读命名管道的代码运行之后才能退出:
首先复习一下open函数
open :
int open(const char*pathname,int flags)
int open(const char *pathname,int flags,ode_t. mode);
pathname:要打开或创建的目标文件
flags:打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算构成flags。
O_WRONLY: 只写打开
O_RDONLY:只读打开
O_RDWR:读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT :若文件不存在,则创建它。需要使用mode选项,来指明新文件的访间权限, O_APPEND:追加写
modc:当新创建一个文件的时候,、指定新创建文件的权限;传递一个8进制的数字(就是权限,例的0664)
返回值:
成功:新打开的文件描述符一一文件操怍句柄,文件句柄...失败:-1
这个问题是open打开文件的时候, 默认的情况是阻塞打开,所以就有了下面的现象:
1. 进程只读打开, 阻塞在open, 等待其他进程写打开
2. 进程只写打开, 阻塞在open, 等待其他进程读打开
如果进程是可读可写打开, 则不会阻塞在open
读代码
#include<stdio.h>
2 #include<unistd.h>
3 #include<fcntl.h>
4 int main()
5 {
6 int fd=open("../fifo",O_RDONLY);
7 if(fd<0)
8 {
9 perror("open");
10 return 0;
11 }
12 char arr[1024]={0};
13 read(fd,arr,100);
14 printf("%s\n",arr);
15 close(fd);
16 return 0;
17 }
准备
执行结果:
2.共享内存
共享内存的原理:
在物理内存里开辟一段空间,(函数开辟空间)
不同的进程通过页表把物理内存上的同一段空间映射到进程虚拟地址空间上,(利用函数给进程虚拟空间附加共享内存)
不同的进程通过操作自己的进程虚拟地址空间操作虚拟地址,进而操作共享内存,达到进程间通信.
原理图:
不同的进程就可以通过自己的进程虚拟地址空间映射到同一片物理内存进行操作.
1.在内存上创建共享区的函数
参数:
参数:
key:共享内存标识符
size:共享内存大小
shmflg:获取/创建共享内存时,传递的属性信息
IPC_CREAT:如果获取的共空内存不存在,则创建
IPC_EXCL | IPC_CREAT:
如果获取的共享内存存在,则函数报错如果获取的共享内存不存在,则创建。
创建时要按位或上文件的权限
成功:返回共享内存操作句柄失败:-1
int main()
6 {
7 //在物理内存上获取共享内存参数:
8 int sh=shmget(0x12121212,1024,IPC_CREAT|0664);
9 if(sh<0)
10 {
11 perror("shmget");
12 return 0;
13 }
2.将物理内存上的共享区附加到进程虚拟地址空间的函数
参数:
shmid:共享内存操作句柄
shmaddr:将共享内存附加到进程虚拟地址空间中共享区当中的第一企地址上。一般让操作系统自己分配,传递NULL
shmflg:以什么权限将共享内存附加到进程当中
SHM_RDONLY:只读 0 : 可读可写(这个设置的是这个进程对共享内存的权限)
返回值:
成功:返回附加的虚拟地址.失败:NULL
//在物理内存上获取共享内存参数:
8 int sh=shmget(0x12121212,1024,IPC_CREAT|0664);
9 if(sh<0)
10 {
11 perror("shmget");
12 return 0;
13 }
14 //附加到虚拟地址空间的共享区
15 void * s=shmat(sh,NULL,0);
16 if(s==NULL)
17 {
18 perror("shmat");
19 return 0;
20 }
21
如何查看共享内存连接的进程呢
ipcs命令(没有命令行参数)
注意:附加的进程数量需要在进程不退出的情况下才能看到,如果进程退出,就会和共享内存分离,nattch的值会--
3,分离函数,既然能把共享内存加到共享区上去,所以就得能分离出来.
参数:shmat函数得返回值(意味着把这个虚拟地址所在得进程从共享内存上剥离)
在死循环前面加shmdt函数后进程就会从共享内存上分离出来,需要注意,这时候进程还没有结束.
ipcs之后nattch的值是0
成功返回0;失败返回-1
4.操作共享内存的函数
参数:
shmid:共享内存的操作句柄
cmd:告诉shmct1函数需要完成什么功能
IPC_SET :设置共享内存属性信息
IPc_STAT :获取共享丙存属性信息
IPC_RMID :删除共享内存,第三个参数传递NULL
buf:共享内存数据结构
5.共享内存的删除命令 ipcrm -m [shmid]
.一旦共享内存被删除掉之后,共享内存的在物理内存当中的空间被销毁了·如果删除的共享内存的时候,共享内存附加的讲理数量为0,则内核当中描述该共享内存的结构体也被释放了
·如果删除的共享内存的时候,共享内存附加的进程数量不为0,则会将该共享内存的key,变成Ox00000000。表示当前共享内存不能被其他进程所
附加,共享内存的状态会被设置为destory。附加的进行一旦全部退出之后,↓该共享内存在内核的结构体会被操作系统释放掉
情况一:没有附加进程的情况下删
情况2:附加的情况下删.
共享内存的特性
共享内存的生命周期跟随操作系统,所以需要手动删除
共享内存写和字符串相似能覆盖写也能追加写,读的时候就是正常访问地址
代码验证写
#include<stdio.h>
2 #include<sys/shm.h>
3 #include<unistd.h>
4 #include<string.h>
5 int main()
6 {
7 //在物理内存上获取共享内存参数:
8 int sh=shmget(0x12121212,1024,IPC_CREAT|0664);
9 if(sh<0)
10 {
11 perror("shmget");
12 return 0;
13 }
14 //附加到虚拟地址空间的共享区
15 void * s=shmat(sh,NULL,0);
16 if(s==NULL)
17 {
18 perror("shmat");
19 return 0;
20 }
E> 21 strcpy(s,"hello world");
22 return 0;
23 }
代码验证读:
#include<stdio.h>
#include<sys/shm.h>
#include<unistd.h>
int main()
{
int sh=shmget(0x12121212,1024,IPC_CREAT);
if(sh<0)
{
perror("shmat");
return 0;
}
void*a=shmat(sh,NULL,0);
if(a==NULL)
{
return 0;
}
printf("%s\n",(char*)a);
return 0;
}