进程间通信

目录

一、管道

        1、匿名管道

        2、命名管道

二、消息队列

三、共享存储

四、信号量


一、管道

        1、匿名管道

                        有亲缘关系的进程实现进程间通信

 #include <unistd.h>

 int pipe(int pipefd[2]);

        pipefd[0]--->read
        pipefd[1]--->write

        特点:
                1. 半双工通讯
                2. 必须凑齐读端和写端
                3. 所有写端关闭,read就会返回0
                4. 所有读端关闭,write产生SIGPIPE异常,如果此信号忽略,则write返回-1并errno值设置为EPIPE
                5. 有容量,写满管道,write会阻塞
                6. 读空管道,read会阻塞

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <stdlib.h>

#define BUFSIZE	32

static int cpFl(int rfd, int wfd);
int main(int argc, char *argv[])
{
	int fd;
	int pfd[2] = {};
	pid_t pid;

	if (argc < 2)
		return 1;

	if (-1 == pipe(pfd)) {
		perror("pipe()");
		exit(1);
	}
	pid = fork();
	if (-1 == pid) {
		perror("fork()");
		exit(1);
	}
	if (0 == pid) {
		close(pfd[1]);
		cpFl(pfd[0], 1);
		close(pfd[0]);
		exit(0);
	}

	close(pfd[0]);
	fd = open(argv[1], O_RDONLY);
	if (-1 == fd) {
		perror("open()");
		close(pfd[1]);
		exit(1);
	}
	cpFl(fd, pfd[1]);
	close(pfd[1]);
	close(fd);

	wait(NULL);

	exit(0);
}

static int cpFl(int rfd, int wfd)
{
	char buf[BUFSIZE] = {};
	int cnt;
	
	while (1) {
		cnt = read(rfd, buf, BUFSIZE);
		if (-1 == cnt) {
			perror("read()");
			return -1;
		}
		if (0 == cnt)
			break;
		write(wfd, buf, cnt);
	}
	return 0;
}


        2、命名管道

        不仅局限与有亲缘关系的进程,所有的进程都能够操作此管道

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);

可参考mkfifo函数

二、消息队列

        就是一个能应用于进程间数据交换的队列,符合队列特点
                `int msgget(key_t key, int flags)`
                `int msgrcv(int msgid, void *buf, int size, int type, int flag)`
                `int msgsnd(int msgid, const void *buf, int size, int flag)`
                `int msgctl(int msgid, int cmd, struct msgid_ds *ds)`

三、共享存储

1. shm(是否有亲缘关系都可)
    1. 创建
    `int shmget(key_t key, int size, int flag)`
    2. 映射
    `void *shmat(int shmid, const void *addr, int flag)`
    `int shmdt(void *addr)`
    3. 获得状态/销毁
    `int shmctl(int shmid, int cmd, struct shmid_ds *ds)`
2. mmap(仅限于有亲缘关系的进程)
    `void *mmap(void *addr, int size, int prot, int flag, int fd, offet_t off)`

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>

int main(void)
{
	int shmid;
	pid_t pid;
	char *ptr;

	// 创建共享内存
	shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | IPC_EXCL | 0600);
	if (-1 == shmid) {
		perror("shmget()");
		exit(1);
	}

	// 创建子进程
	pid = fork();
	if (-1 == pid) {
		perror("fork()");
		goto ERROR;
	}
	// 各自映射
	if (0 == pid) {
		ptr = (char *)shmat(shmid, NULL, 0);
		if ((void *)-1 == ptr) {
			perror("shmat()");
			exit(1);
		}
		strcpy(ptr, "good morning");
		shmdt(ptr);
		exit(0);
	}

	wait(NULL);
	ptr = shmat(shmid, NULL, 0);
	// if error
	sleep(10);
	puts(ptr);
	shmdt(ptr);

	// 销毁
	shmctl(shmid, IPC_RMID, NULL);
	return 0;
ERROR:
	shmctl(shmid, IPC_RMID, NULL);
	exit(1);
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>

// 有亲缘关系的进程得到一端共享内存

int main(void)
{
	pid_t pid;
	void *ptr = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);

	pid = fork();
	if (-1 == pid) {
		perror("fork()");
		exit(1);
	}
	if (0 == pid) {
		memcpy(ptr, "good afternoon", 14);
		exit(0);
	}
	wait(NULL);
	puts(ptr);
	munmap(ptr, 1024);

	return 0;
}

四、信号量

                保证多进程资源竞争的时候同步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值