Linux常用的进程间通信方式有:
1、管道(pipe)和有名管道(FIFO)
2、信号(signal)
3、消息队列
4、共享内存
5、信号量
6、套接字
***********************************管道通信实例************************************
pipe只能用于父进程和子进程之间通信。
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main()
{
int pipe_fd[2]; //管道描述符
pid_t pid; //进程描述符
char buf_r[100]; //读取数据的缓冲区
char* p_wbuf;
int r_num; //read函数返回值
memset( buf_r, 0, sizeof( buf_r ) );
/*创建管道*/
if( pipe( pipe_fd ) < 0 )
{
printf("pipe create error\n");
return -1;
}
/**父进程向管道里写入数据,子进程读取父进程写入的内容**/
/*创建子进程*/
if( ( pid = fork() ) == 0 ) //子进程运行
{
printf("\n");
close( pipe_fd[1] ); //子进程
sleep(2);
if( ( r_num = read( pipe_fd[0] ,buf_r, 100 ) ) >0 )//从管道头部读取数据
{
printf(" %d numbers read from the pipe is %s\n", r_num, buf_r );
}
close( pipe_fd[0] );
exit(0);
}
else if( pid > 0 ) //父进程
{
close( pipe_fd[0] ); //关闭管道的读数据端
if( write( pipe_fd[1], "Hello", 5 ) !=-1 )
printf("parent write1 Hello!\n");
if( write( pipe_fd[1], "Pipe", 5 ) != -1)
printf("parent write2 Pipe!\n");
close( pipe_fd[1] ); //关闭管道的写入端,
sleep(3);
waitpid( pid, NULL, 0); //等待子进程结束
exit(0);
}
return 0;
}
*****************************FIFO实例***********************************
FIFO可以用于同一系统上的任意两个进程间通信。
fifo_write.c
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO_SERVER "/tmp/myfifo"
main(int argc,char** argv)
{
int fd;
char w_buf[100];
int nwrite;
/*打开管道*/
fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);
if(argc==1)
{
printf("Please send something\n");
exit(-1);
}
strcpy(w_buf,argv[1]);
/* 向管道写入数据 */
if((nwrite=write(fd,w_buf,100))==-1)
{
if(errno==EAGAIN)
printf("The FIFO has not been read yet.Please try later\n");
}
else
printf("write %s to the FIFO\n",w_buf);
}
fifo_read.c
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO "/tmp/myfifo"
main(int argc,char** argv)
{
char buf_r[100];
int fd;
int nread;
/* 创建管道 */
if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
printf("cannot create fifoserver\n");
printf("Preparing for reading bytes...\n");
memset(buf_r,0,sizeof(buf_r));
/* 打开管道 */
fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);
if(fd==-1)
{
perror("open");
exit(1);
}
while(1)
{
memset(buf_r,0,sizeof(buf_r));
if((nread=read(fd,buf_r,100))==-1)
{
if(errno==EAGAIN)
printf("no data yet\n");
}
printf("read %s from FIFO\n",buf_r);
sleep(1);
}
pause(); /*暂停,等待信号*/
unlink(FIFO); //删除文件
}
*******************************信号通信实例********************************
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
void my_func(int sign_no)
{
if(sign_no==SIGINT)
printf("I have get SIGINT\n");
else if(sign_no==SIGQUIT)
printf("I have get SIGQUIT\n");
}
int main()
{
printf("Waiting for signal SIGINT or SIGQUIT \n ");
/*注册信号处理函数*/
signal(SIGINT, my_func);
signal(SIGQUIT, my_func);
pause();
exit(0);
}
****************************共享内存通信实例*************************************************
/*
**使用共享内存实现父进程和子进程之间的通信
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define PERM S_IRUSR|S_IWUSR
int main(char argc, char *argv[])
{
int shmid; //共享内存标识符
char *p_addr, *c_addr;
if( argc !=2 )
{
fprintf( stderr, "Usage:%s\n\a", argv[0] );
exit(1);
}
/**创建共享内存*/
if( ( shmid = shmget( IPC_PRIVATE, 1024, PERM) ) == -1 )
{
fprintf(stderr, "Create Share Memory Error:%\n\a", strerror(errno) );
exit(1);
}
/*创建子进程*/
if( fork() ) //父进程写
{
p_addr = shmat( shmid, 0, 0 );
memset( p_addr, '\0', 1024 );
strncpy( p_addr, argv[1], 1024 );
wait(NULL);
exit(0);
}
else //子进程读
{
sleep(1);
c_addr = shmat( shmid, 0, 0);
printf("Client get %s\n", c_addr );
exit(0);
}
}
/*
**消息队列
*/
#include <sys/types.h>
#include <sys/msg.h>
#include <unistd.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct msg_buf
{
int mtype;
char data[255];
};
int main()
{
key_t key;
int msgid;
int ret;
struct msg_buf msgbuf;
/*获得文件键值*/
key = ftok( "/tmp/msg", 'a' );
printf("key = [%x]\n", key);
/**创建消息队列*/
msgid = msgget( key, IPC_CREAT|0666 );
if(msgid == -1 )
{
perror("msgget");
exit(1);
}
/*给消息队列中发送一条消息*/
msgbuf.mtype = getpid(); //填充msg_buf结构体
strcpy(msgbuf.data, "fang haha");
ret = msgsnd( msgid, &msgbuf, sizeof(msgbuf.data), IPC_NOWAIT );
if( ret == -1 )
{
perror("msgsnd");
exit(1);
}
/*从消息队列中读取消息*/
memset( &msgbuf, 0, sizeof(msgbuf) );
ret = msgrcv( msgid, &msgbuf, sizeof(msgbuf), getpid(), IPC_NOWAIT );
if( ret == -1 )
{
perror("msgrcv");
exit(1);
}
puts(msgbuf.data);
}