#include
功能:创建一无名管道
原型
int pipe(int fd[2]);
参数
fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端
返回值:成功返回0,失败返回错误代码
*A pipe is created using pipe(2), which creates a new pipe and returns
two file descriptors, one referring to the read end of the pipe, the
other referring to the write end. Pipes can be used to create a
communication channel between related processes; see pipe(2) for an example.*/
#include
#include
#include
#include
#include
#include
#include
int main()
{
int pipe_fd[2]={0};//输出型参数 fork之前数据共享
if(pipe(pipe_fd)<0)
{
perror("pipe");
return 1;
}
pid_t id =fork();
if(id<0)
{
perror("fork");
return 2;
}
else if(id == 0)//写
{
close(pipe_fd[0]);
const char* msg = "test for pipe!";
int i=3;
while(i--)
{
write(pipe_fd[1],msg,strlen(msg));//从msg 向1号文件描述符里写msg长度个字节
sleep(1);
}
close(pipe_fd[1]);
exit(0);//关闭并退出
}
else{//father
close(pipe_fd[1]);
char ret[66];
while(1)
{
ret[0]='\0';
ssize_t ss = read(pipe_fd[0],ret,sizeof(ret)-1);
if(ss>0)
{
ret[ss]='\0';
printf("childe:%s\n",ret);
}
else if (ss==0)
{
printf("read done,childe quit\n");
break;
}
else{
perror("read");
break;
}
}
int ss=0;
auto it = waitpid(-1,&ss,0); //不wait pid 后太会有一堆孤儿进程...
if(it >0)
{
printf("wait done father quit\n");
}
else{
perror("waitpid");
}
}
return 0;
}
read端 | write端 | 结果 |
---|---|---|
不读 | 写 | write阻塞 |
读 | 不写 | read阻塞 |
不读且关闭 | 写 | 无意义的写入,浪费系统资源,写进程会被OS终止掉 |
读 | 不写且关闭 | read读取到0,文件结束 |
---//命令行
$ mkfifo filename
---//程序里创建
int mkfifo(const char *filename,mode_t mode);
---//查看帮助
man 7 fifo //先进先出
man mkfifo
[saul@VM-12-7-centos tt801]$ while :; do echo "test for mkfifo"; sleep 1; done >fio
[saul@VM-12-7-centos ~]$ cat < fio
test for mkfifo
test for mkfifo
test for mkfifo
....
---//srever.c
#include
#include
#include
#include
#include
#define FIFO "./fifo" //定义文件及路径
int main()
{
int ret = mkfifo(FIFO, 0644);
if(ret < 0){
perror("mkfifo");
return 1;
}
int fd = open(FIFO, O_RDONLY);//读方式打开
if(fd<0){
perror("open");
return 2;
}
char buffer[128];
while(1){
buffer[0] = 0;
ssize_t s = read(fd, buffer, sizeof(buffer)-1);
if(s > 0){
buffer[s] = 0;
printf("client# %s\n", buffer);
}
else if(s == 0){
printf("client quit...\n");
break;
}
else{
break;
}
}
close(fd);
return 0;
}
---//cilent.c
#include
#include
#include
#include
#include
#include
#define FIFO "./fifo"
int main()
{
int fd = open(FIFO, O_WRONLY);
if(fd<0){
perror("open");
return 2;
}
char buffer[128];
while(1){
printf("Please Enter# ");
fflush(stdout);
buffer[0] = 0;
ssize_t s = read(0, buffer, sizeof(buffer)-1);
if(s > 0){
buffer[s] = 0;
write(fd, buffer, strlen(buffer));
}
else if(s == 0){
break;
}
else{
break;
}
}
close(fd);
return 0;
}
key_t ftok(const char *pathname, int proj_id);
:提供shmget()
中的K值。
int shmget(key_t key, size_t size, int shmflg);
:用来创建共享内存
shmflg:
如果IPC_CREAT and IPC_EXCL
都设置,则获取一块儿新的共享内存;如果已经存在,返回-1.IPC_CREAT
单独设置,没有共贡献内存,创建之。有就获取之。void *shmat(int shmid, const void *shmaddr, int shmflg);
:将共享内存段关联到进程地址空间。
shmaddr
为NULL,核心自动选择一个地址shmflg
:设置为0.int shmdt(const void *shmaddr);
:将共享内存段与当前进程脱离,去关联。
shmaddr
: 由 shmat 所返回的指针ipcs -m / ipcs
ipcrm -m shmid
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
:
cmd
:宏,有多个;设置成其中一个:IPC_RMID
。标记要销毁的段。只有在最后一个进程将其分离后(即当关联结构 shmid 的nattch 成员为零时),该段才会被实际销毁。buf
:NULLIPC_CREAT and IPC_EXCL
这样的标志位:
shmflg
,这样参数就可以表示多种状态。----//server.c
#include "comm.h"
#include
#include
#include
#include
int main()
{
//创建key
key_t k = ftok(PATH_NAME, PROJ_ID);
if(k < 0){
perror("ftok");
return 1;
}
printf("key: %x\n", k);
//创建共享内存
int shmid = shmget(k, SIZE, IPC_CREAT | IPC_EXCL | 0644); //共享内存如果不存在,创建之,如果存在,出错返回!
if(shmid < 0){
perror("shmget");
return 2;
}
printf("shmid: %d\n", shmid);
//将当前进程和共享内存进行关联!
char *start = (char*)shmat(shmid, NULL, 0);
printf("server already attach on shared memory!\n");
//开始使用共享内存通信了
//TODO
for( ; ; ){
printf("%s\n", start);
//sleep(1);
}
//将当前进程和共享内存去关联
shmdt(start);
printf("server already dattch off shared memory!\n");
//释放共享内存
shmctl(shmid, IPC_RMID, NULL);
printf("delete shm!\n");
return 0;
}
----//client.c
#include "comm.h"
#include
#include
#include
#include
int main()
{
//获取同一个key
key_t k = ftok(PATH_NAME, PROJ_ID);
if(k < 0){
perror("ftok");
return 1;
}
printf("%x\n", k);
//不需要自己创建shm,获取共享内存
int shmid = shmget(k, SIZE, IPC_CREAT);
if(shmid < 0){
perror("shmget");
return 2;
}
//client挂接自己到shm
char * start = (char*)shmat(shmid, NULL, 0);
//TODO
char c = 'A';
while(c <= 'Z'){
start[c - 'A'] = c;
c++;
sleep(2);
}
//去关联
shmdt(start);
return 0;
}
----//makefile
CC=gcc //编译器
.PHONY:all
all:client server
client:client.c
$(CC) -o $@ $^
server:server.c
$(CC) -o $@ $^
.PHONY:clean
clean:
rm -f client server
shmid
vs key
ipc_perm*
类型存储的,把各种类型的结构体切片放进去,是通过强转做到的,要访问结构体中其它成员,再强转回来就行了~msgget
、msgsnd
、msgrcv
、msgctl
… int semget(key_t key, int nsems, int semflg);
nsems
:系统可以允许你一次创建多个信号量。 int semctl(int semid, int semnum, int cmd, ...);
- OS通过一众数据结构:结构体,指针,指针数组,双向链表等管理软硬件资源,向上提供接口…