linux system ipc
一、无名管道
- 无名管道时半双工的,就是对于一个管道来讲,只能读或者写
- 无名管道只能在相关、有共同祖先的进程间使用
- 一个fork或者exec调用创建的子进程继承了父进程的文件描述符
1,打开和关闭管道
int pipe(int filedes[2]);
//在你从一个管道中读写,管道必须存在
//如果成功建立管道,则会打开两个文件描述符,并把它们的值保存在一个数值
//第一个文件描述符用于读数据,第二个文件描述符用于写数据
//出错返回-1,同时设置errno
//关闭一个管道用close()函数
//不能两端进行读写
/读写无名管道例子/
int main()
{
int fd[2];//管道描述符
char buf[100];//存放管道收发数据
int len;//记录长度
pipe(fd);
memset(buf,0,sizeof(buf));//清空buf
int pid = fork();
if(pid == 0)
{
close(fd[1]);//关闭写管道
while(len = read(fd[0],buf,sizeof(buf) >0)//len大于
{
write(STDOUT_FIFLNO,buf,len);
}
close(fd[0]);
}
else
{
close(fd[0]);//关闭读管道
strcpy(buf,"hello world\n");
write(fd[1],buf,sizeof(buf));
close(fd[1]);
waitpid(pid,NULL,0);
}
return 0;
}
二、有名管道(FIFO)
- 有名管道是持久稳定的
- 它们存在于文件系统中
- 可以让无关联的进程之间通信
1,用shell命令建立有名管道mkfifo [option] name
#mkfifo fifo1 //创建一个有名管道
#cat < fifo1 //通过cat向管道读取数据
#ls > fifo1 //通过ls向管道输出数据
2,函数创建FIFO
int mkfifo(const char *pathname,mode_t mode)
//函数执行成功返回0,否则返回-1,并设置变量errno
int unlink(const char*pathname)
//删除fifo文件,执行成功返回0,否则返回-1,并设置变量errno
int main()
{
mkfifo("fifo1",0666);
//mode:rw-rw-rw为权限
unlink("fifo1");
return 0;
}
3,读写FIFO文件
//读FIFO例子
int main()
{
int len = 0;
char buf[100];
memset(buf,0,sizeof(buf));
int fd = open("fifo1",O_RDONLY);//只读方式
while(len = read(fd[0],buf,sizeof(buf) >0)
{
printf("%s",buf);
memset(buf,0,sizeof(buf));
}
close(fd);
return 0;
}
//写FIFO例子
int main()
{
char buf[100];
memset(buf,0,sizeof(buf));
int fd = open("fifo1",O_WRONLY);//只写方式
while(1)
{
read(STDIN_FIFLNO,buf,sizeof(buf));
if(buf[0] == '0')//如果输入字符0,退出循环
break;
write(fd,buf,strlen(buf));
memset(buf,0,sizeof(buf));
}
close(fd);
return 0;
}
4,共享内存
- 共享内存是内核处于在多个进程之间交换
信息二留出的一块内存区 - 如果段的权限设置恰当,每个要访问该段
内存的进程都可以把它映像到自己的私有空间 - 如果一个进程更新了段中的数据,其他进程也
会立即看到更新 - 由一个进程创建的段,也可以由另一个进程读写
- 每个进程都把自己对共享进程内存的映像放到自
己的内存空间
1)创建共享内存区
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key,size_t size,int shm_flg);
//参数key既可以是IPC_PRIVATE,也可以是ftok函数返回的一个关键字
//参数size指定段的大小。
//参数flag:八进制数,0XXX。转化为二进制权限
//shmget成功返回段标示符,失败返回-1。
int shmctl(id, IPC_RMID, 0);
//删除共享内存的函数
/创建共享内存区/
int main()
{
int shmid = shmget (IPC_PRIVATE,1024,0666);
if(shmid < 0)
printf ("error\n");
else
printf ("success\n");
return 0;
//在命令行执行ipcs -m 显示成功创建的共享内存信息
//nattch:已经附加到这个内存的进程数
//在命令行执行ipcrm shm shmid 删除共享内存
}
2)附加共享内存区
void *shmat (int shmid,const void *shmaddr,int shmfg );
//参数shmid是要附加的共享内存标示符
//总是把参数shmaddr设置为0
//参数shmflg可以为SHM_RDONLY,这意味着附加段是只读
//shmat成功返回被附加了段的地址,失败返回-1,并设置变量errno
int shmdt (const void *shmaddr );
//函数shmdt将附加在shmaddr的段从调用进程的地址空间分离出去,这个地址必须shmat返回
/附加,释放共享内存区/
int main(int argc,char *args[])
{
char* shmbuf;
int shmid = 0;
if(arg > 1)
{
shmid = atoi(args[1]);//传入共享内存id
shmbuf = shmat(shmid,0,0);
sleep(60);
shmdt(shmbuf);
}
return 0;
}
3)读写共享内存区
/附加,释放共享内存区/
int main(int argc,char *args[])
{
char* shmbuf;
int shmid = 0;
if(arg > 2)
{
shmid = atoi(args[1]);//传入共享内存id
shmbuf = shmat(shmid,0,0);
if (atoi(args[2] == 1))//write shared mem
{
scanf ("%s\n",shmbuf);
}
if(atoi(args[2] == 2)//read shared mem
{
printf ("%s\n",shmbuf);
}
shmdt(shmbuf);
}
return 0;
}