系统编程3:进程间通信

pipe函数; fd【0】读;fd【1】写
无名管道:有血缘关系的进程,比如父子进程,管道也属于文件;

例句:ret =pipe(fd); //创建无名管道
pid =fork(); //先创建管道,再创建子进程。
else if (0 == pid) //子进程
{
close(fd[0]);
a++;
ret = write(fd[1], &a, sizeof(int)); //数据a写入管道
if (-1 == ret)
{
perror(“write”);
exit(1);
}
printf(“Child a = %d\n”, a);
}
ret = read(fd[0], &a, sizeof(int)); //从管道读数据
if (-1 == ret)
{
perror(“read”);
exit(1);
}
a++;
printf(“Parent a = %d\n”, a);

**

mkfifo:有名管道。

**
例句:ret = mkfifo(“fifo.tmp”, 00700); //创建有名管道文件
fd = open(“fifo.tmp”, O_RDONLY); //只读方式打开管道文件
unlink(“fifo.tmp”); //删除管道文件
fd = open(“fifo.tmp”, O_WRONLY); //只写的方式打开管道文件

消息队列
1.创建消息队列(获取)
msgget();
2.读写消息队列
msgsnd(); msgrcv();
3删除消息队列
msgctl();
关于消息队列的代码:
文件1中;

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>

#define MSGKEY 1234

struct msgbuf {
long mtype; /* message type, must be > 0 /
char mtext[100]; /
message data */
};

int main()
{
int ret;
int msgid;
struct msgbuf m;
pid_t pid;

msgid = msgget(MSGKEY, IPC_CREAT | IPC_EXCL);  //创建消息队列
if (-1 == msgid)
{
	perror("msgget");
	exit(1);
}

pid = fork();
if (-1 == pid)
{
	perror("fork");
	exit(1);
}
else if (0 == pid)   //子进程发送数据
{
	while (1)
	{
		memset(&m, 0, sizeof(m));
		scanf("%s", m.mtext);
		m.mtype = 1;

		ret = msgsnd(msgid, &m, sizeof(m.mtext), 0);
		if (-1 == ret)
		{
			perror("msgsnd");
		}
		if (!strcmp(m.mtext, "bye"))
		{
			m.mtype = 2;
			ret = msgsnd(msgid, &m, sizeof(m.mtext), 0);
			if (-1 == ret)
			{
				perror("msgsnd");
			}
			break;
		}
	}
}
else                //父进程接收数据 
{
	while (1)
	{
		ret = msgrcv(msgid, &m, sizeof(m.mtext), 2, 0);  //接收消息类型为2
		if (-1 == ret)
		{
			perror("msgrcv");
		}
		if (!strcmp(m.mtext, "bye"))
		{
			kill(pid, SIGINT);
			break;
		}
			
		printf("\t\t%s\n", m.mtext);
		memset(&m, 0, sizeof(m));
	}
	sleep(1);
	msgctl(msgid, IPC_RMID, NULL);   //删除消息队列
}


return 0;

}

文件2中:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>

#define MSGKEY 1234

struct msgbuf {
long mtype; /* message type, must be > 0 /
char mtext[100]; /
message data */
};

int main()
{
int msgid, ret;
struct msgbuf m;

msgid = msgget(MSGKEY, 0);   //获取消息队列
if (-1 == msgid)
{
	perror("msgget");
	exit(1);
}

pid_t pid = fork();
if (-1 == pid)
{
	perror("fork");
	exit(1);
}
else if (0 == pid)  //子进程发送数据
{
	while (1)
	{
		scanf("%s", m.mtext);
		m.mtype = 2;   //发送的消息类型为2

		ret = msgsnd(msgid, &m, sizeof(m.mtext), 0);
		if (-1 == ret)
		{
			perror("msgsnd");
		}
		if (!strcmp(m.mtext, "bye"))
		{
			m.mtype = 1;
			msgsnd(msgid, &m, sizeof(m.mtext), 0);
			break;
		}
		memset(&m, 0, sizeof(m));
	}
}
else   //父进程接收数据
{
	while (1)
	{
		memset(&m, 0, sizeof(m));
		ret = msgrcv(msgid, &m, sizeof(m.mtext), 1, 0);
		if (-1 == ret)
		{
			perror("msgrcv");
		}
		if (!strcmp(m.mtext, "bye"))
		{
			kill(pid, SIGINT);
			break;
		}
		printf("\t\t%s\n", m.mtext);
	}
}


return 0;

}

关于共享内存:
步骤:
1.创建(获取)共享内存
shmget();
2.映射
shmat();
3.使用共享内存
4.解除映射
shmat();
5删除共享内存
shmct();
代码部分:
文件1;

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define SHMKEY 1234
#define SHMSIZE 4096 //以页为单位分配
#define SEMKEY 1234

union semun {
int val; /* Value for SETVAL */
struct semid_ds buf; / Buffer for IPC_STAT, IPC_SET */
unsigned short array; / Array for GETALL, SETALL */
struct seminfo __buf; / Buffer for IPC_INFO(Linux specific) */
};

void sem_p(int id)
{
struct sembuf s;
s.sem_num = 0; //第0个信号量
s.sem_op = -1; //减一操作
s.sem_flg = SEM_UNDO; //如果进程出现异常退出,信号量恢复初始值
int ret = semop(id, &s, 1); //p操作
if (-1 == ret)
{
perror(“semop”);
}
}

void sem_v(int id)
{
struct sembuf s;
s.sem_num = 0; //第0个信号量
s.sem_op = 1; //加一操作
s.sem_flg = SEM_UNDO; //如果进程出现异常退出,信号量恢复初始值
int ret = semop(id, &s, 1); //p操作
if (-1 == ret)
{
perror(“semop”);
}
}

int main()
{
int shmid, ret;
void *shmaddr;
int count = 100;

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

int semid = semget(SEMKEY, 1, IPC_CREAT | IPC_EXCL);  //创建信号量(1个)
if (-1 == semid)
{
	perror("semget");
	exit(1);
}

union semun s;
s.val = 1;   //二值信号量
ret = semctl(semid, 0, SETVAL, s);  //初始化信号量
if (-1 == ret)
{
	perror("semctl");
	exit(1);
}

shmaddr = shmat(shmid, NULL, 0);  //共享内存映射,返回映射后的地址(虚拟内存的地址)
if (NULL == shmaddr)
{
	perror("shmat");
	exit(1);
}

*(int *)shmaddr = count;   //把共享数据写入共享内存

while (1)
{
	sem_p(semid);     //减一操作
	count = *(int *)shmaddr; //获取数据
	if (count < 0)
	{
		sem_v(semid);
		break;
	}
	printf("%d count = %d\n", getpid(), count);
	count--;
	usleep(10000);
	*(int *)shmaddr = count;  //数据写回共享内存
	sem_v(semid);     //加一操作
}

shmdt(shmaddr);                  //解除映射
sleep(1);
shmctl(shmid, IPC_RMID, NULL);   //删除共享内存
semctl(semid, 0, IPC_RMID);      //删除信号量

return 0;

}
文件2:
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define SHMKEY 1234
#define SHMSIZE 4096 //以页为单位分配
#define SEMKEY 1234

union semun {
int val; /* Value for SETVAL */
struct semid_ds buf; / Buffer for IPC_STAT, IPC_SET */
unsigned short array; / Array for GETALL, SETALL */
struct seminfo __buf; / Buffer for IPC_INFO(Linux specific) */
};

void sem_p(int id)
{
struct sembuf s;
s.sem_num = 0; //第0个信号量
s.sem_op = -1; //减一操作
s.sem_flg = SEM_UNDO; //如果进程出现异常退出,信号量恢复初始值
int ret = semop(id, &s, 1); //p操作
if (-1 == ret)
{
perror(“semop”);
}
}

void sem_v(int id)
{
struct sembuf s;
s.sem_num = 0; //第0个信号量
s.sem_op = 1; //加一操作
s.sem_flg = SEM_UNDO; //如果进程出现异常退出,信号量恢复初始值
int ret = semop(id, &s, 1); //p操作
if (-1 == ret)
{
perror(“semop”);
}
}

int main()
{
int shmid, ret;
void *shmaddr;
int count = 100;

shmid = shmget(SHMKEY, SHMSIZE, 0);   //获取共享内存
if (-1 == shmid)
{
	perror("shmget");
	exit(1);
}

int semid = semget(SEMKEY, 1, 0);  //获取信号量(1个)
if (-1 == semid)
{
	perror("semget");
	exit(1);
}

shmaddr = shmat(shmid, NULL, 0);  //共享内存映射,返回映射后的地址(虚拟内存的地址)
if (NULL == shmaddr)
{
	perror("shmat");
	exit(1);
}

while (1)
{
	sem_p(semid);     //减一操作
	count = *(int *)shmaddr; //获取数据
	if (count < 0)
	{
		sem_v(semid);
		break;
	}
	printf("%d count = %d\n", getpid(), count);
	count--;
	usleep(10000);
	*(int *)shmaddr = count;  //数据写回共享内存
	sem_v(semid);     //加一操作
}

shmdt(shmaddr);                  //解除映射

return 0;

}

**关于信号量的知识:
1.创建信号量
semget();
2.初始化信号量
semctl();
3.pv操作
semop();
4。删除信号量
semctl();
代码部分:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值