目录
进程间通信方法汇总
有名管道
管道只支持两个进程通信,且半双工通信
当打开管道文件时,阻塞,直到文件的另一端也被打开
当一端进程退出时,另一端在读,则返回0,另一端在写返回-1和信号SIGPIPE
例子 接受端
#include "stdio.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "unistd.h"
#include "errno.h"
#include "string.h"
#include "fcntl.h"
#include <stdlib.h>
#define _PATH_ "./fifo.file"
#define _SIZE_ 100
int main()
{
int ret = mkfifo(_PATH_,0666|S_IFIFO);
char * buf;
buf = (char *)malloc(_SIZE_);
memset(buf,'\0',sizeof(buf));
if(ret == -1){
printf("mkfilo failed!\n");
return 1;
}
int fd = open(_PATH_,O_RDWR|O_CREAT,0644);
if(fd<0)
{
printf("open failed\n");
}
// while(1){
// int readfifo = read(fd,buf,_SIZE_-1);
// if(readfifo <0)
// {
// perror("read");
// break;
// }
//printf("%s",buf);
dup2(fd,0);
execl("/bin/bash","bash",(char *)0);
if(strncmp(buf,"quit",4)==0){
// break;
}
// }
close(fd);
remove(_PATH_);
printf("fifo test over!!!!\n");
return 0;
}
发送端:
#include "stdio.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "unistd.h"
#include "errno.h"
#include "string.h"
#include "fcntl.h"
#include "stdlib.h"
#define _PATH_ "./fifo.file"
#define _SIZE_ 100
int main()
{
char * buf;
buf = (char *)malloc(_SIZE_);
memset(buf,'\0',sizeof(buf));
int fd = open(_PATH_,O_RDWR|O_CREAT);
if(fd<0)
{
printf("open failed\n");
exit(1);
}
while(1){
fgets(buf,_SIZE_-1,stdin);
if(sizeof(buf)<0){
perror("fgets");
exit(0);
}
int readfifo = write(fd,buf,_SIZE_);
if(readfifo <0)
{
perror("write");
break;
}
if(strncmp(buf,"quit",4)==0){
close(fd);
exit(0);
}
}
return 0;
}
system v ipc
消息队列
struct msqid_ds
{
struct msqid_ds {
struct ipc_perm msg_perm;
struct msg *msg_first; /* first message on queue,unused */
struct msg *msg_last; /* last message in queue,unused */
__kernel_time_t msg_stime; /* last msgsnd time */
__kernel_time_t msg_rtime; /* last msgrcv time */
__kernel_time_t msg_ctime; /* last change time */
unsigned long msg_lcbytes; /* Reuse junk fields for 32 bit */
unsigned long msg_lqbytes; /* ditto */
unsigned short msg_cbytes; /* current number of bytes on queue */
unsigned short msg_qnum; /* number of messages in queue */
unsigned short msg_qbytes; /* max number of bytes on queue */
__kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */
__kernel_ipc_pid_t msg_lrpid; /* last receive pid */
};
message头文件
#include "stdio.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/msg.h"
#include "unistd.h"
#include "errno.h"
#include "string.h"
#include "fcntl.h"
#include <stdlib.h>
#define _PATH_ "."
#define _PROJ_ID_ 0x6666
#define _SIZE_ 1024
#define CLIENT_TYPE 1
#define SERVER_TYPE 2
struct msgbuf
{
long mtype;
char mtext[_SIZE_];
};
int creat_queue();
int get_queue();
int send_msg(int msgqueue_id,int who,char * msg);
int recv_msg(int msgqueue_id,int want,char out[],int out_len);
int delet_msgqueue(int msgqueue_id);
函数实现
#include "message_server.h"
static int com_creat_queue(int flags)
{
key_t key = ftok(_PATH_,_PROJ_ID_);//创建一个消息队列号
if(key < 0)
{
printf("%d:%s\n",errno,strerror(errno));
return -1;
}
int msg_id = msgget(key,flags);
if(msg_id<0)
{
printf("%d:%s\n",errno,strerror(errno));
return -1;
}
return msg_id;
}
int creat_queue()
{
int flags = IPC_CREAT|IPC_EXCL|0666;
return com_creat_queue(flags);
}
int get_queue()
{
int flags = IPC_CREAT;
return com_creat_queue(flags);
}
int send_msg(int msg_id,int who,char * msg)
{
struct msgbuf _buf;
memset(&_buf,'\0',sizeof(_buf));
_buf.mtype = who;
strncpy(_buf.mtext,msg,sizeof(msg)+1);
// printf("%s\n",msg);
return msgsnd(msg_id,&_buf,sizeof(_buf.mtext),0);
}
int recv_msg(int msg_id,int want,char out[],int out_len)
{
struct msgbuf _buf;
memset(&_buf,'\0',sizeof(_buf));
int ret = msgrcv(msg_id,&_buf,sizeof(_buf.mtext),want,0);
if(ret<=-1)
{
printf("%d:%s\n",errno,strerror(errno));
return -1;
}
memset(out,'\0',out_len);
strcpy(out,_buf.mtext);
return 0;
}
int delet_msgqueue(int msg_id)
{
int ret=msgctl(msg_id,IPC_RMID,NULL);
if(ret<0)
{
printf("%d:%s\n",errno,strerror(errno));
return -3;
}
return 0;
}
例子server
#include "message_server.h"
int server()
{
int msg_id = creat_queue();
if(msg_id<0)
{
msg_id = get_queue();
//printf("%s\n", strerror(errno));
// return -1;
}
char buf[_SIZE_];
while(1)
{
usleep(100);
memset(buf,'\0',sizeof(buf));
int ret = recv_msg(msg_id,SERVER_TYPE,buf,sizeof(buf));
if(ret<0){
printf("%d:%s\n",errno,strerror(errno));
return -1;
}
printf("%s",buf);
int sen = send_msg(msg_id,CLIENT_TYPE,buf);
if (sen<0)
{
printf("%d:%s\n",errno,strerror(errno));
return -1;
}
if(strncmp(buf,"quit",4)==0)
{
break;
}
}
delet_msgqueue(msg_id);
return 0;
}
int main()
{
server();
return 0;
}
例子clinet
#include "message_server.h"
int client()
{
int msg_id = get_queue();
if(msg_id<0)
{
printf("%s\n", strerror(errno));
return -1;
}
char buf[_SIZE_];
while(1)
{
usleep(100);
memset(buf,'\0',sizeof(buf));
fgets(buf,sizeof(buf),stdin);
int ret = send_msg(msg_id,SERVER_TYPE,buf);
if(ret<0){
printf("%d:%s\n",errno,strerror(errno));
return -1;
}
memset(buf,'\0',sizeof(buf));
int sen = recv_msg(msg_id,CLIENT_TYPE,buf,sizeof(buf));
if (sen<0)
{
printf("%d:%s\n",errno,strerror(errno));
return -1;
}
if(strncmp(buf,"quit",4)==0)
{
break;
}
}
return 0;
}
int main()
{
client();
return 0;
}
信号量
简单例子
#include "stdio.h"
#include "sys/types.h"
#include "sys/msg.h"
#include "unistd.h"
#include "errno.h"
#include "string.h"
#include <sys/ipc.h>
#include <sys/sem.h>
#define MAX_SEMAPHORES 5
int main(int argc, char const *argv[])
{
int i,ret,semid;
unsigned short sem_array[MAX_SEMAPHORES];
unsigned short sem_read_array[MAX_SEMAPHORES];
union semun{
int val;
struct semid_ds *buf;
unsigned short * array;
}arg;
semid = semget(IPC_PRIVATE,MAX_SEMAPHORES,IPC_CREAT|0666);//创建信号量
if(semid!=-1)
{
for (int i = 0; i < MAX_SEMAPHORES; ++i)
{
sem_array[i] = (unsigned short)(i+1);
}
arg.array = sem_array;
ret = semctl(semid,0,SETALL,arg);//设置所有消息
if(ret == -1)printf("SETALL failed (%d)\n", errno);
arg.array = sem_read_array;
ret = semctl(semid,0,GETALL,arg);//获得所有信号
if(ret == -1) printf("GETALL failed (%d)\n",errno);
for (int i = 0; i < MAX_SEMAPHORES; ++i)
{
printf("Semaphore %d,value %d\n",i,sem_read_array[i]);
}
for(i = 0;i<MAX_SEMAPHORES;i++)
{
ret = semctl(semid,i,GETVAL);//单个获得信号
}
ret = semctl(semid,0,IPC_RMID);
}
else printf("Gould not allocate semaphore (%d)\n",errno);
return 0;
}
共享内存
文件句柄传输
接受句柄
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<errno.h>
#define SOCK_FILE "chandler"
int create_local_sock(char *sockfile)
{
int local_fd=0;
struct sockaddr_un serveraddr;
if(-1==(local_fd=socket(AF_LOCAL,SOCK_STREAM,0)))
{
perror("socket");exit(EXIT_FAILURE);
}
bzero(&serveraddr,sizeof(serveraddr));
serveraddr.sun_family=AF_LOCAL;
strncpy(serveraddr.sun_path, sockfile,strlen(sockfile));
if(-1==connect(local_fd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)))
{
perror("connect");exit(EXIT_FAILURE);
}
return local_fd;
}
static int recv_fd(int fd, int *fd_to_recv,char *buf,int len)
{
struct cmsghdr *cmsg;
cmsg = alloca(sizeof(struct cmsghdr)+sizeof(fd_to_recv));
cmsg->cmsg_len = sizeof(struct cmsghdr)+sizeof(fd_to_recv);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
struct msghdr msg;
msg.msg_control = cmsg;
msg.msg_controllen = cmsg->cmsg_len;
msg.msg_name = NULL;
msg.msg_namelen = 0;
struct iovec iov[3];
iov[0].iov_base = buf;
iov[0].iov_len = len;
msg.msg_iov = iov;
msg.msg_iovlen =3;
if(recvmsg(fd, &msg, 0) < 0)
{
printf("recvmsg error, errno is %d\n", errno);
fprintf(stderr,"recvmsg failed. errno : %s\n",strerror(errno));
return errno;
}
memcpy(fd_to_recv, CMSG_DATA(cmsg), sizeof(fd_to_recv));
if(msg.msg_controllen != cmsg->cmsg_len)
{
*fd_to_recv = -1;
}
return 0;
}
int main(int argc,char *argv[])
{
int sock_fd=0;
int file_fd;
char *ptr="now write data to file\n";
char buf[129];
memset(buf,'\0',128);
sock_fd=create_local_sock(SOCK_FILE);
recv_fd(sock_fd,&file_fd,buf,128);
write(file_fd,ptr,strlen(ptr));
printf("recv message:%s\n",buf);
unlink(SOCK_FILE);
}
发送句柄
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<errno.h>
#include<fcntl.h>
#define SOCK_FILE "chandler"
int create_local_sock(char *sockfile)
{
int local_fd;
struct sockaddr_un myaddr;
if(-1==(local_fd=socket(AF_LOCAL,SOCK_STREAM,0)))
{
perror("socket");exit(EXIT_FAILURE);
}
bzero(&myaddr,sizeof(myaddr));
myaddr.sun_family=AF_LOCAL;
strncpy(myaddr.sun_path, sockfile,strlen(sockfile));
if(-1==bind(local_fd,(struct sockaddr *)&myaddr,sizeof(myaddr)))
{
perror("bind");exit(EXIT_FAILURE);
}
if(-1==listen(local_fd,5))
{
perror("listen");exit(EXIT_FAILURE);
}
int new_fd;
struct sockaddr_un peeraddr;
int len=sizeof(peeraddr);
new_fd=accept(local_fd,(struct sockaddr *)&peeraddr,&len);
if(-1==new_fd)
{
perror("accept");exit(EXIT_FAILURE);
}
return new_fd;
}
send_fd(int sock_fd,char *file)
{
int fd_to_send;
if(-1==(fd_to_send=open(file,O_RDWR|O_APPEND)))
{
perror("open");exit(EXIT_FAILURE);
}
struct cmsghdr *cmsg;
cmsg = alloca(sizeof(struct cmsghdr)+sizeof(fd_to_send));
cmsg->cmsg_len = sizeof(struct cmsghdr)+sizeof(fd_to_send);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
memcpy(CMSG_DATA(cmsg), &fd_to_send, sizeof(fd_to_send));
struct msghdr msg;
msg.msg_control = cmsg;
msg.msg_controllen = cmsg->cmsg_len;
msg.msg_name= NULL;
msg.msg_namelen = 0;
struct iovec iov[3];
iov[0].iov_base = "hello ";
iov[0].iov_len = strlen("hello ");
iov[1].iov_base = "this is yangzd, ";
iov[1].iov_len = strlen("this is yangzd, ");
iov[2].iov_base = "and you?";
iov[2].iov_len = strlen("and you?");
msg.msg_iov = iov;
msg.msg_iovlen = 3;
if(sendmsg(sock_fd, &msg, 0) < 0)
{
printf("sendmsg error, errno is %d\n", errno);
fprintf(stderr,"sendmsg failed. errno : %s\n",strerror(errno));
return errno;
}
return 1;
}
int main(int argc,char *argv[])
{
int sock_fd=0;
unlink(SOCK_FILE);
if(argc != 2)
{
printf("pls usage %s file_send\n",argv[0]);
exit(EXIT_FAILURE);
}
sock_fd=create_local_sock(SOCK_FILE);
if(send_fd(sock_fd,argv[1])!=1)
{
printf("send error");exit(EXIT_FAILURE);
}
}
mmap
void *mmap(void * addr,size_t length,int prot,int flags,int fd,off_t offxet)
第一个参数:映射地址 为空则将地址返回值返回
第二个参数:映射大小
第三个参数:操作 PROT_WRITE PROT_READ PROT_EXEC
第四个参数:权限 MAP_SHARED
第五个参数:映射的地址
第六个参数:偏移
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PATH "./archivo.txt"
int main() {
struct stat filestat;
char *p;
int fd;
int removed;
size_t size;
fd = open(PATH, O_CREAT | O_RDWR);
if (fd == -1) {
perror("open");
exit(1);
}
if (fstat(fd, &filestat) == -1) {
perror("stat");
exit(1);
}
size = filestat.st_size;
p = mmap (0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (p == MAP_FAILED) {
perror("mmap");
exit(1);
}
int i;
removed = 0;
for (i = 0; i < size; i++) {
if (p[i] == 'b') {
memmove(&p[i], &p[i+2], strlen(p) - i);
removed++;
continue;
}
printf("%c", p[i - removed]);
}
int new_size = ((size - removed * sizeof(char)) * 2) + 1;
if (ftruncate(fd, new_size) == -1)//预分配一段内存
{
perror("ftruncate");
exit(1);
}
p = mremap(p, size, new_size, MREMAP_MAYMOVE, 0);
if (p == MAP_FAILED) {
perror("mremap");
exit(1);
}
int j = 0;
for (i = i + 1; i < new_size; i++) {
p[i] = toupper(p[j]);
printf("%c", p[i]);
j++;
}
if (munmap(p, new_size) == -1) {
perror("munmap");
exit(1);
}
close(fd);
exit(0);
}