Inter-Process Communication Linux development --IPCs

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/qq_25490573/article/details/102616561

table of Contents

 

Interprocess communication method summary

Named Pipes

Examples receiving end

The sender:

system v ipc

message queue

message header

Function to achieve

Examples of server

Examples clinet

signal

A simple example

Shared memory

File handle transmission

Handle accepted

Send a handle

mmap


Interprocess communication method summary

Named Pipes

Pipeline supports only two-process communication and half-duplex communication

When the file open pipe, block until the other end is also opened file

When the process exits at one end, the other end of the read, 0 is returned, the other end of the write signals and -1 SIGPIPE

Examples receiving end

#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;
}

The sender:

#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

message queue

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);
}

 

Guess you like

Origin blog.csdn.net/qq_25490573/article/details/102616561