操作系统实验——进程通信(FIFO、shared memory)

参考原文链接

共享内存

编译指令:

gcc shared_memory.cpp -I/usr/local/include/ -L/usr/local/lib -lrt -o shared_mem

代码:

/**
* Sample code for sharing memory between processes
* Two processes will iteratively increase a counter which values stored in a shared memory
*
*/
#include <stdio.h>
#include <unistd.h> // for fork()
#include <sys/mman.h> // for shared memory created
#include <sys/stat.h> // for mode constants
#include <fcntl.h> // for O_* constant
#define SHARED_OBJ_NAME "/somename"
// shared data struct
struct message
{
int pid;
int counter;
};
bool write_message(int pid, int value)
{
int shmFd = shm_open(SHARED_OBJ_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
ftruncate(shmFd, sizeof(message));
message *msg_ptr = (message*)mmap(NULL, sizeof(message), PROT_READ | PROT_WRITE, MAP_SHARED, shmFd, 0);
printf("Process %d: Increase the counter.\n", pid);
msg_ptr->pid = pid;
msg_ptr->counter = value;
munmap(msg_ptr, sizeof(message));
// remember to close to not hit an error of
// opening too many files
close(shmFd);
return true;
}
bool read_message(int curr_pid, int &curr_value)
{
int shmFd = shm_open(SHARED_OBJ_NAME, O_RDWR, S_IRUSR | S_IWUSR);
ftruncate(shmFd, sizeof(message));
message *msg_ptr = (message*)mmap(NULL, sizeof(message), PROT_READ | PROT_WRITE, MAP_SHARED, shmFd, 0);
if (msg_ptr->pid == curr_pid)
{
printf("Process %d: No new msg available.\n", curr_pid);
return false;
}
else
{
printf("Process %d: Receive %d from PID %d.\n", curr_pid, msg_ptr->counter, msg_ptr->pid);
curr_value = msg_ptr->counter;
munmap(msg_ptr, sizeof(message));
}
close(shmFd);
return true;
}
int main(int argc, char **argv)
{
printf("Init the initial value.\n");
write_message(-1, 0);
// create a child process by calling folk,
// it returns a non-zero pid for parent process and 0 for child process created
pid_t pid = fork();
//--- PARENT PROCESS
if (pid != 0)
{
for (int i = 0; i < 5; i++)
{
int value;
// only write message if reading sucessfully
if (read_message(pid, value)) write_message(pid, ++value);
sleep(0.1);
}
}
//--- CHILD PROCESS
else
{
for (int j = 0; j < 5; j++)
{
int value;
if (read_message(pid, value)) write_message(pid, ++value);
sleep(0.1);
}
}
printf("=========== End of process %d\n", pid);
//shm_unlink(SHARED_OBJ_NAME);
return 0;
}

运行结果:

Init the initial value.
Process -1: Increase the counter.
Process 440735: Receive 0 from PID -1.
Process 440735: Increase the counter.
Process 440735: Receive 2 from PID 0.
Process 440735: Increase the counter.
Process 440735: No new msg available.
Process 440735: No new msg available.
Process 440735: Receive 4 from PID 0.
Process 440735: Increase the counter.
=========== End of process 440735
Init the initial value.
Process -1: Increase the counter.
Process 0: Receive 1 from PID 440735.
Process 0: Increase the counter.
Process 0: Receive 3 from PID 440735.
Process 0: Increase the counter.
Process 0: Receive 5 from PID 440735.
Process 0: Increase the counter.
Process 0: No new msg available.
Process 0: No new msg available.
=========== End of process 0

FIFO

编译指令:

gcc fifo.cpp -I/usr/local/include/ -L/usr/local/lib -lrt -o fifo
/**
* Example for using named pipe for communicating between processes
* This demo is for a unidirectional named pipe which transfer data in one direction
*/
#include "csapp.h"
#define NAMED_PIPE "/var/lock/pipename"
// shared data struct
struct message
{
int pid;
int counter;
};
int main(int argc, char **argv)
{
// create the named pipe (fifo) with permission
int ret = mkfifo(NAMED_PIPE, 0666);
if (ret < 0)
printf("Error when creating FIFO. %s\n", strerror(errno));
// create a child process by calling folk,
// it returns a non-zero pid for parent process and 0 for child process created
pid_t pid = fork();
//--- the parent process will write to the pipe only
if (pid != 0)
{
int fd = open(NAMED_PIPE, O_WRONLY);
for (int i = 0; i < 5; i++)
{
message msg;
msg.pid = pid;
msg.counter = i;
printf("Process %d: Write %d.\n", pid, i);
ret = write(fd, &msg, sizeof(msg));
if (ret < 0)
printf("Process %d: Error while writing message. %s\n", pid, strerror(errno));
sleep(0.1);
}
close(fd);
}
//-- child process will read only
else
{
int fd = open(NAMED_PIPE, O_RDONLY);
for (int i = 0; i < 5; i++)
{
message msg;
ret = read(fd, &msg, sizeof(msg));
if (ret < 0)
printf("Process %d: Error while reading message. %s\n", pid, strerror(errno));
printf("Process %d: Received value %d from the parent process %d.\n", pid, msg.counter, msg.pid);
sleep(0.1);
}
close(fd);
}
unlink(NAMED_PIPE);
return 0;
}

运行结果:

Process 424351: Write 0.
Process 424351: Write 1.
Process 424351: Write 2.
Process 424351: Write 3.
Process 424351: Write 4.
Process 0: Received value 0 from the parent process 424351.
Process 0: Received value 1 from the parent process 424351.
Process 0: Received value 2 from the parent process 424351.
Process 0: Received value 3 from the parent process 424351.
Process 0: Received value 4 from the parent process 424351.

消息队列

使用消息队列的步骤,定义消息结构->创建消息队列->通过消息队列向进程A发送消息->通过消息队列接收进程A的消息。
每条消息都有一个标识或“类型”,以便进程可以选择适当的消息,并且进程必须共享一个公共“密钥”才能首先获得对队列的访问权限。
进程可以从队列发送或接收消息,队列必须通过msgget()操作初始化,发送和接收消息分别由msgsnd( )和msgrcv()函数执行。

下面的程序实现父进程和子进程之间C/S方式的通信。

#include "csapp.h"
struct mesg_buffer {
long mesg_type;
char mesg_text[100];
} message;
int main(int argc, char **argv) {
pid_t pid = fork();
if (pid != 0) {
key_t key;
int msgid;
// generate unique key
key = ftok("somefile", 65);
msgid = msgget(key, 0666 | IPC_CREAT);
message.mesg_type = 1;
printf("Insert message : ");
// scanf("%s", message.mesg_text);
fgets(message.mesg_text, 100, stdin);
// send message
msgsnd(msgid, &message, sizeof(message), 0);
// display the message
printf("Message sent to server : %s\n", message.mesg_text);
} else {
key_t key;
int msgid;
// generate unique key
key = ftok("somefile", 65);
msgid = msgget(key, 0666 | IPC_CREAT);
printf("Waiting for a message from client...\n");
// receive message
msgrcv(msgid, &message, sizeof(message), 1, 0);
// display the message
printf("Message received from client : %s \n", message.mesg_text);
// to destroy the message queue ;
msgctl(msgid, IPC_RMID, NULL);
}
return 0;
}

编译、运行指令:

$ gcc msgqueue.cpp -I/usr/local/include/ -L/usr/local/lib -o msgque
$ ./msgque
使用stdin输入:
$ hello world!
posted @   Coldarra  阅读(193)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示