无名管道:
int pipe(int fd[2]);
返回值:如果系统调用成功,返回0。如果系统调用失败返回- 1:
errno = ENFILE (没有空闲的文件描述符)
EMFILE (系统文件表已满)
EFAULT (fd数组无效)
#include"lib.h" //封装的头文件
int main()
{
int fd[2]={0}
char buf[100]={0};
if(pipe(fd)==-1)
{
perror("pipe");
return -1;
}
if(fork()>0)
{
while(1)
{
scanf("%s",buf);
write(fd[1],buf,strlen(buf));
}
}
else
{
//子进程读
while(1)
{
memset(buf,0,sizeof(buf));
//如果写端不存在,则认为读到数据的末尾,读出的字节为0
if(read(fd[0],buf,sizeof(buf))==0)
{
return 0;
}
printf("read=%s\n",buf);
}
}
close(fd[0]);
close(fd[1]);
}
命名管道:
int mkfifo(const char *pathname, mode_t mode) ;//命名管道的创建
返回:若成功则为0,若出错则为 -1
demo:
#include"lib.h"
#include<errno.h>
#define FIFO_HANDLE_NEMA "/tmp/fifo_handle"
#define FIFO_CLIENT_NAME "/tmp/fifo_client_%d"
struct ps_fifo_struct{
pid_t pid;
char str[64];
};
int main()
{
int fifo_handle,fifo_client;
struct ps_fifo_struct ps_fifo;
char client_fifo_name[64];
int read_len;
char answer_str[64];
//创建有名管道
if((mkfifo(FIFO_HANDLE_NEMA,0666)==-1) && (errno != 17))
{
perror("mkfifo");
return -1;
}
//打开管道
fifo_handle=open(FIFO_HANDLE_NEMA,O_RDONLY);
if(fifo_handle==-1)
{
perror("name_fife open");
return -1;
}
do{
read_len=read(fifo_handle,&ps_fifo,sizeof(ps_fifo));
if(read_len>0)
{
//读
printf("hai,%d ,I am %d I have received the string:%s\n",ps_fifo.pid,getpid(),ps_fifo.str);
memset(client_fifo_name,0,64);
sprintf(client_fifo_name,FIFO_CLIENT_NAME,ps_fifo.pid);
fifo_client=open(client_fifo_name,O_WRONLY);
ps_fifo.pid=getpid();
if(fifo_client!=-1)
{
//写
write(fifo_client,&ps_fifo,sizeof(ps_fifo));
close(fifo_client);
}
}
}while(read_len>0);
close(fifo_handle);
unlink(FIFO_HANDLE_NEMA);
return 0;
}
#include"lib.h"
#define FIFO_HANDLE_NEMA "/tmp/fifo_handle"
#define FIFO_CLIENT_NAME "/tmp/fifo_client_%d"
struct ps_fifo_struct{
pid_t pid;
char str[64];
};
int main()
{
int fifo_handle,fifo_client;
struct ps_fifo_struct ps_fifo;
char client_fifo_name[64];
//打开管道 写
fifo_handle=open(FIFO_HANDLE_NEMA,O_WRONLY);
if(fifo_handle==-1)
{
perror("name_fife open");
return -1;
}
ps_fifo.pid=getpid();
memset(client_fifo_name,0,sizeof(client_fifo_name));
sprintf(client_fifo_name,FIFO_CLIENT_NAME,ps_fifo.pid);
if(access(client_fifo_name,F_OK)==-1)
{
if(mkfifo(client_fifo_name,0666)!=0)
{
fprintf(stderr,"Could Not Create FIFO %s\n",client_fifo_name);
return -1;
}
}
sprintf(ps_fifo.str,"hello I am %d",ps_fifo.pid);
//printf("%d sent:%s \n",ps_fifo.pid,ps_fifo.str);
write(fifo_handle,&ps_fifo,sizeof(ps_fifo));
fifo_client=open(client_fifo_name,O_RDONLY);
if(fifo_client!=-1)
{
if(read(fifo_client,&ps_fifo,sizeof(ps_fifo))>0)
{
printf("received from %d : %s\n",ps_fifo.pid,ps_fifo.str);
close(fifo_client);
}
}
close(fifo_handle);
unlink(client_fifo_name);
return 0;
}
运行截图:
消息队列:
消息队列的实现包括创建和打开队列、添加消息、读取消息这几种操作。
struct msgbuf
{
long mtype; /* type of message */
char mtext[1]; /* message text */
};
int msgget (key_t key, int flag)
参数flag可以为以下:
IPC_CREAT、IPC_EXCL、0666
返回:成功返回消息队列描述字,否则返回-1。
int msgsnd (int msgid, struct msgbuf *msgp, size_t msgsz, int flag) //把消息添加到消息队列中(也就是发送消息)
返回:成功返回0,否则返回-1。
*msgp 指向要发送消息的指针,消息一般是一个带有long类型的消息类型结构体
msgsz 发送消息的长度,不包括消息类型
flag 控制在消息队列已满时的选项
IPC_NOWAIT 立即返回错误-1 (非阻塞)
0 等待消息队列有可用空间 (阻塞)
int msgrcv (int msgid, struct msgbuf *msgp, size_t msgsz,long msgtyp, int flag) //读取信息
返回:成功返回读出消息的实际字节数,否则返回-1
参数三:
msgtyp是期望接收的消息类型;0:队列中第一个可用消息;>0:相同消息类型的第一个消息;<0:类型等于或小于msgtyp绝对值的消息。 mtype必须是大于0的数。
参数四:
flag在消息队列没有没有相应类型的消息可以接受时:IPC_NOWAIT指明立即返回,返回值为-1;若IPC_NOWAIT标志被清除,则发送进程挂起以等待第一条相同类型的消息到达。
int msgctl(int msgid, int cmd, struct msqid_ds *buf);
msgid:消息队列标识符。
cmd:采取的动作。
IPC_STAT:该命令用来获取消息队列信息,返回的信息存贮在buf指向的msgid结构中;
IPC_SET:该命令用来设置消息队列的属性,要设置的属性存储在buf指向的msgid结构中;
IPC_RMID:删除msgid标识的消息队列;
demo:
#include"lib.h"
struct msgbuf
{
long mtype; //消息类型
char mtext[1024];
};
int main()
{
struct msgbuf mbuf;
mbuf.mtype=1;
strcpy(mbuf.mtext,"hello");
//创建和打开信息
int msgid=msgget(1,IPC_CREAT|0666);
if(msgid==-1)
{
perror("msgget");
return -1;
}
msgsnd(msgid,&mbuf,sizeof(mbuf.mtext),0);
return 0;
}
#include"lib.h"
struct msgbuf
{
long mtype; //消息类型
char mtext[1024];
};
int main()
{
struct msgbuf mbuf;
//创建和打开信息
int msgid=msgget(1,IPC_CREAT|0666);
if(msgid==-1)
{
perror("msgget");
return -1;
}
参数四要和来的消息类型一样,否则收不到消息
msgrcv(msgid,&mbuf,sizeof(mbuf.mtext),1,0);
printf("recv=%s\n",mbuf.mtext);
//msgctl(msgid,IPC_RMID,NULL);
return 0;
}
共享内存:
步骤:
一、创建共享内存,使用shmget函数。
二、映射共享内存,将这段创建的共享内存映射到具体的进程空间去,使用shmat函数。
int shmget ( key_t key, int size, int shmflg );
用来获得共享内存区域的ID,如果不存在指定的共享区域就创建相应的区域。
参数二:内存空间大小
参数三:IPC_CREAT IPC_EXCL 0666
返回值:如果成功,返回共享内存段标识符。
如果失败,则返回- 1:
void *shmat ( int shmid, char *shmaddr, int shmflg);
返回值:如果成功,则返回共享内存段连接到进程中的地址,失败则返回(void *)- 1.
当一个进程不在需要共享的内存段时,它将会把内存段从其地址空间中脱离。
int shmdt ( void *shmaddr );
返回值:成功返回0,失败返回- 1:
int shmctl(int shm_id,int cmd,struct shmid_ds *buf);
cmd:
IPC_STAT:该命令用来获取共享内存信息,返回的信息存贮在buf指向的结构中;
IPC_SET:该命令用来设置共享内存的属性,要设置的属性存储在buf指向的msqid结构中;
IPC_RMID:删除shm_id标识的共享内存
#include "lib.h"
int main()
{
key_t key=ftok("/home/ubuntu",1);
int shmid=shmget(key,1024,IPC_CREAT|0666);
pid_t pid=fork();
if(pid==0)
{
int semid=semget(key,1,IPC_CREAT|0666);
struct sembuf msem;
msem.sem_num=0;
msem.sem_op=-1;
msem.sem_flg=SEM_UNDO;
int *p=shmat(shmid,NULL,0);
while(1)
{
semop(semid,&msem,1);
printf("%d\n",*p);
sleep(1);
}
}
else
{
int semid=semget(key,1,IPC_CREAT|0666);
struct sembuf msem;
msem.sem_num=0;
msem.sem_op=1;
msem.sem_flg=SEM_UNDO;
int *num=shmat(shmid,NULL,0);
while(1)
{
scanf("%d",num);
semop(semid,&msem,1);
}
}
}