Skip to content

3 - Inter process communication

  • There are 2 kinds: SYSTEM V and POSIX in unix based
  • Introduced: Early UNIX (AT&T System V, 1983).
  • APIs:
    • Message Queues: msgget, msgsnd, msgrcv, msgctl
    • Shared Memory: shmget, shmat, shmdt, shmctl
    • Semaphores: semget, semop, semctl
  • Introduced: POSIX.1b (1993), more modern and portable.

  • APIs:

    • Message Queues: mq_open, mq_send, mq_receive, mq_close, mq_unlink
    • Shared Memory: shm_open, mmap, shm_unlink
    • Semaphores: sem_open, sem_wait, sem_post, sem_unlink
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
    pid_t pid = fork();
    int shared = 10;
    if (pid == 0) { // Child process
        shared += 1;
        printf("child: shared = %d\n", shared);
    } else { // Parent process
        shared += 2;
        printf("parent: shared = %d\n", shared);
        wait(NULL);
    }
    return 0;
}

OUTPUT

Terminal window
c@c:~/cos3105$ ./create_process2
parent: shared = 12
child: shared = 10
write_shared_memory.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/shm.h>
#include<string.h>
int main()
{
int i;
void *shared_memory;
char buff[100];
int shmid;
/* creates shared memory segment with key 2345, having size 1024 bytes.
IPC_CREAT is used to create the shared segment if it does not exist.
0666 are the permisions on the shared segment */
shmid=shmget((key_t)2345, 1024, 0666|IPC_CREAT);
printf("Key of shared memory is %d\n",shmid);
//process attached to shared memory segment
shared_memory=shmat(shmid,NULL,0);
//this prints the address where the segment is attached with this process
printf("Process attached at %p\n",shared_memory);
printf("Enter some data to write to shared memory\n");
//get some input from user
read(0,buff,100);
//data written to shared memory
strcpy(shared_memory,buff);
printf("You wrote : %s\n",(char *)shared_memory);
}

OUTPUT

Write Shared Memory

read_shared_memory.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>
int main()
{
int i;
void *shared_memory;
char buff[100];
int shmid;
shmid=shmget((key_t)2345, 1024, 0666);
printf("Key of shared memory is %d\n",shmid);
shared_memory=shmat(shmid,NULL,0); //process attached to shared memory segment
printf("Process attached at %p\n",shared_memory);
printf("Data read from shared memory is : %s\n",(char *)shared_memory);
}

OUTPUT

Read Shared Memory

#include<stdio.h>
#include<stdlib.h>
#include <sys/wait.h>
#include<unistd.h>
#include<sys/shm.h>
#include<string.h>
int main()
{
void *shared_memory;
char buff[100];
int shmid;
pid_t pid = fork();
if (pid == 0) {
printf("Child process:\n");
/* creates shared memory segment with key 2345, having size 1024 bytes.
IPC_CREAT is used to create the shared segment if it does not exist.
0666 are the permisions on the shared segment */
shmid=shmget((key_t)2345, 1024, 0666|IPC_CREAT);
printf("Key of shared memory is %d\n",shmid);
//process attached to shared memory segment
shared_memory=shmat(shmid,NULL,0);
//this prints the address where the segment is attached with this process
printf("Process %d attached at %p\n",getpid(),shared_memory);
strcpy(buff,"Krit Chomaitong");
//data written to shared memory
strcpy(shared_memory,buff);
printf("You wrote : %s\n",(char *)shared_memory);
} else {
sleep(3);
printf("Parent process:\n");
shmid=shmget((key_t)2345, 1024, 0666);
printf("Key of shared memory is %d\n",shmid);
shared_memory=shmat(shmid,NULL,0); //process attached to shared memory segment
printf("Process %d attached at %p\n",getpid(),shared_memory);
printf("Data read from shared memory is : %s\n",(char *)shared_memory);
wait(NULL);
}
return 0;
}

OUTPUT

Terminal window
c@c:~/cos3105/tutorial$ make run
./bin/myproject
Child process:
Key of shared memory is 0
Process 3228 attached at 0x75d7b67fc000
You wrote : Krit Chomaitong
Parent process:
Key of shared memory is 0
Process 3227 attached at 0x75d7b67fc000
Data read from shared memory is : Krit Chomaitong
  • Normally mmap will use file which is managed by OS for shared data among processes,
  • But MAP_ANONYMOUS will not use file but use same physical memory location for share data between child and parent
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
    // Create shared integer
    int *shared_num = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    *shared_num = 10;
    if (fork() == 0) {
        // Child process
        printf("Child sees: %d\n", *shared_num);
        *shared_num = 20;
        printf("Child changed it to: %d\n", *shared_num);
    } else {
        // Parent process
        sleep(1);  // Let child run first
        printf("Parent sees: %d\n", *shared_num);  // Will show 20
        wait(NULL);
    }
    return 0;
}

OUTPUT

Terminal window
c@c:~/cos3105$ ./create_process3
Child sees: 10
Child changed it to: 20
Parent sees: 20
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>
int main() {
int pipefd[2];
pid_t pid;
// Create pipe
if (pipe(pipefd) == -1) {
perror("pipe failed");
exit(1);
}
// Fork process
pid = fork();
if (pid == -1) {
perror("fork failed");
exit(1);
}
if (pid == 0) {
// Child process - writer
close(pipefd[0]); // Close read end
printf("Child: Sending message...\n");
write(pipefd[1], "Hello", 5);
close(pipefd[1]); // Close write end
printf("Child: Message sent, exiting\n");
} else {
// Parent process - reader
close(pipefd[1]); // Close write end
char buffer[10];
memset(buffer, 0, sizeof(buffer)); // Initialize buffer
printf("Parent: Waiting for message...\n");
ssize_t bytes_read = read(pipefd[0], buffer, 5);
if (bytes_read > 0) {
printf("Parent: Received message: '%s'\n", buffer);
} else {
printf("Parent: Failed to read message\n");
}
close(pipefd[0]); // Close read end
// Wait for child to finish
wait(NULL);
printf("Parent: Child process finished\n");
}
return 0;
}

OUTPUT

Terminal window
c@c:~/cos3105$ ./message_passing
Parent: Waiting for message...
Child: Sending message...
Child: Message sent, exiting
Parent: Received message: 'Hello'
Parent: Child process finished
  • Write
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main() {
mkfifo("/tmp/mypipe", 0666);
int fd = open("/tmp/mypipe", O_WRONLY);
write(fd, "Hello from writer!", 18);
close(fd);
printf("Message sent\n");
return 0;
}

OUTPUT

Terminal window
c@c:~/cos3105$ ./writer
Message sent
  • Read
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
char buffer[100];
int fd = open("/tmp/mypipe", O_RDONLY);
read(fd, buffer, 18);
close(fd);
printf("Message received: %s\n", buffer);
// Clean up
unlink("/tmp/mypipe");
return 0;
}

OUTPUT

Terminal window
c@c:~/cos3105$ ./reader
Message received: Hello from writer!
  • For send/receive for message queues, it needs to create key and id for distinguish messages.
  1. Generate a Key (ftok()) that is a unique identifier for multple processes can share.

    key_t key = ftok(path, proj_id);
  2. Get/Create Message Queue ID (msgget())

    int msgid = msgget(key, 0666 | IPC_CREAT);
  3. Send message

    #include<stdlib.h>
    #include<stdio.h>
    #include<string.h>
    #include<unistd.h>
    #include<sys/types.h>
    #include<sys/ipc.h>
    #include<sys/msg.h>
    #define MAX_TEXT 512
    struct msgbuf {
    long mtype; /* message type, must be > 0 */
    char mtext[MAX_TEXT]; /* message data */
    };
    int main(){
    struct msgbuf message;
    key_t key = ftok(".", 'A');
    if (key == -1) {
    perror("ftok failed");
    return 1;
    }
    int msgid = msgget(key, 0666 | IPC_CREAT);
    if (msgid == -1) {
    perror("msgget failed");
    return 1;
    }
    strcpy(message.mtext,"Test Message Queue");
    message.mtype = 1; // message type
    if(msgsnd(msgid,(void *)&message, MAX_TEXT,0)==-1) // msgsnd returns -1 if the message is not sent
    {
    perror("msgsnd failed");
    return 1;
    }
    return 0;
    }
  4. Check message queues

    Terminal window
    c@c:~/cos3105/lab3_module$ ipcs -q
    ------ Message Queues --------
    key msqid owner perms used-bytes messages
    0x41000272 2 c 666 1536 1
  5. Receive message

    #include<stdlib.h>
    #include<stdio.h>
    #include<string.h>
    #include<unistd.h>
    #include<sys/types.h>
    #include<sys/ipc.h>
    #include<sys/msg.h>
    #define MAX_TEXT 512
    struct msgbuf {
    long mtype; /* message type, must be > 0 */
    char mtext[MAX_TEXT]; /* message data */
    };
    int main(){
    struct msgbuf message;
    key_t key = ftok(".", 'A');
    if (key == -1) {
    perror("ftok failed");
    return 1;
    }
    int msgid = msgget(key, 0666 | IPC_CREAT);
    if (msgid == -1) {
    perror("msgget failed");
    return 1;
    }
    // Pick message queue that msg_type = 1
    if(msgrcv(msgid, &message, sizeof(message.mtext), 1, 0)==-1){
    perror("msgrcv failed");
    return 1;
    }
    printf("Received: %s\n",message.mtext);
    return 0;
    }

    OUTPUT

    Terminal window
    c@c:~/cos3105$ ./test
    Received: Test Message Queue
  6. Check message queues

    Terminal window
    c@c:~/cos3105/lab3_module$ ipcs -q
    ------ Message Queues --------
    key msqid owner perms used-bytes messages
    0x41000272 2 c 666 0 0
  • Server
Server waiting for connection...
Client connected!
Received: Hello from client!

OUTPUT

Terminal window
c@c:~/cos3105$ ./socket_file_server
Server waiting for connection...
Client connected!
Received: Hello from client!
  • Client
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>
int main() {
int client_fd;
struct sockaddr_un addr;
char buffer[100];
// Create socket
client_fd = socket(AF_UNIX, SOCK_STREAM, 0);
// Setup address
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/tmp/simple_socket");
// Connect to server
connect(client_fd, (struct sockaddr*)&addr, sizeof(addr));
printf("Connected to server!\n");
// Send message
send(client_fd, "Hello from client!", 18, 0);
// Receive response
recv(client_fd, buffer, sizeof(buffer), 0);
printf("Server said: %s\n", buffer);
// Cleanup
close(client_fd);
return 0;
}

OUTPUT

Terminal window
Connected to server!
Server said: Hello from server!
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
int main() {
printf("Configuring local address...\n");
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
struct addrinfo *bind_address;
if (getaddrinfo(0, "3030", &hints, &bind_address) != 0) {
fprintf(stderr, "getaddrinfo() failed.\n");
return 1;
}
printf("Creating socket...\n");
int socket_listen;
socket_listen = socket(bind_address->ai_family,
bind_address->ai_socktype, bind_address->ai_protocol);
if (socket_listen < 0) {
fprintf(stderr, "socket() failed. (%d)\n", errno);
freeaddrinfo(bind_address);
return 1;
}
// Enable address reuse to avoid "Address already in use" error
int yes = 1;
if (setsockopt(socket_listen, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {
fprintf(stderr, "setsockopt() failed. (%d)\n", errno);
close(socket_listen);
freeaddrinfo(bind_address);
return 1;
}
printf("Binding socket to local address...\n");
if (bind(socket_listen, bind_address->ai_addr, bind_address->ai_addrlen)) {
fprintf(stderr, "bind() failed. (%d)\n", errno);
close(socket_listen);
freeaddrinfo(bind_address);
return 1;
}
freeaddrinfo(bind_address);
printf("Listening...\n");
if (listen(socket_listen, 10) < 0) {
fprintf(stderr, "listen() failed. (%d)\n", errno);
close(socket_listen);
return 1;
}
printf("Waiting for connection...\n");
struct sockaddr_storage client_address;
socklen_t client_len = sizeof(client_address);
int socket_client = accept(socket_listen,
(struct sockaddr*) &client_address, &client_len);
if (socket_client < 0) {
fprintf(stderr, "accept() failed. (%d)\n", errno);
close(socket_listen);
return 1;
}
printf("Client is connected... ");
char address_buffer[100];
if (getnameinfo((struct sockaddr*)&client_address,
client_len, address_buffer, sizeof(address_buffer), 0, 0,
NI_NUMERICHOST) == 0) {
printf("%s\n", address_buffer);
} else {
printf("unknown\n");
}
printf("Reading request...\n");
char request[1024];
int bytes_received = recv(socket_client, request, sizeof(request) - 1, 0);
if (bytes_received > 0) {
printf("Received %d bytes.\n", bytes_received);
request[bytes_received] = '\0'; // Null terminate for safety
// Uncomment the next line if you want to see the request
// printf("Request: %.*s", bytes_received, request);
} else {
printf("Failed to receive data or connection closed.\n");
close(socket_client);
close(socket_listen);
return 1;
}
printf("Sending response...\n");
// Get time first
time_t timer;
time(&timer);
char *time_msg = ctime(&timer);
// Calculate content length (remove newline from ctime)
int time_len = strlen(time_msg);
if (time_len > 0 && time_msg[time_len - 1] == '\n') {
time_msg[time_len - 1] = '\0'; // Remove trailing newline
time_len--;
}
char response_buffer[1024];
int content_length = strlen("Local time is: ") + time_len;
// Build complete HTTP response with proper Content-Length header
int response_len = snprintf(response_buffer, sizeof(response_buffer),
"HTTP/1.1 200 OK\r\n"
"Connection: close\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: %d\r\n"
"\r\n"
"Local time is: %s",
content_length, time_msg);
int bytes_sent = send(socket_client, response_buffer, response_len, 0);
printf("Sent %d of %d bytes.\n", bytes_sent, response_len);
printf("Closing connection...\n");
close(socket_client);
printf("Closing listening socket...\n");
close(socket_listen);
printf("Finished.\n");
return 0;
}

OUTPUT

Terminal window
c@c:~/cos3105$ curl localhost:3030
Local time is: Sun Sep 7 12:53:56 2025
  • Server
/*
* MIT License
*
* Copyright (c) 2018 Lewis Van Winkle
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define _POSIX_C_SOURCE 200112L
#define _DEFAULT_SOURCE
#define _BSD_SOURCE
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define ISVALIDSOCKET(s) ((s) >= 0)
#define CLOSESOCKET(s) close(s)
#define SOCKET int
#define GETSOCKETERRNO() (errno)
int main() {
printf("Configuring local address...\n");
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
struct addrinfo *bind_address;
getaddrinfo(0, "3030", &hints, &bind_address);
printf("Creating socket...\n");
SOCKET socket_listen;
socket_listen = socket(bind_address->ai_family,
bind_address->ai_socktype, bind_address->ai_protocol);
if (!ISVALIDSOCKET(socket_listen)) {
fprintf(stderr, "socket() failed. (%d)\n", GETSOCKETERRNO());
return 1;
}
// Allow socket address reuse
int yes = 1;
if (setsockopt(socket_listen, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
fprintf(stderr, "setsockopt() failed. (%d)\n", GETSOCKETERRNO());
return 1;
}
printf("Binding socket to local address...\n");
if (bind(socket_listen,
bind_address->ai_addr, bind_address->ai_addrlen)) {
fprintf(stderr, "bind() failed. (%d)\n", GETSOCKETERRNO());
return 1;
}
freeaddrinfo(bind_address);
printf("Listening...\n");
if (listen(socket_listen, 10) < 0) {
fprintf(stderr, "listen() failed. (%d)\n", GETSOCKETERRNO());
return 1;
}
printf("Waiting for connections...\n");
while(1) {
struct sockaddr_storage client_address;
socklen_t client_len = sizeof(client_address);
SOCKET socket_client = accept(socket_listen,
(struct sockaddr*) &client_address, &client_len);
if (!ISVALIDSOCKET(socket_client)) {
fprintf(stderr, "accept() failed. (%d)\n", GETSOCKETERRNO());
return 1;
}
char address_buffer[100];
getnameinfo((struct sockaddr*)&client_address,
client_len, address_buffer, sizeof(address_buffer), 0, 0,
NI_NUMERICHOST);
printf("New connection from %s\n", address_buffer);
int pid = fork();
if (pid == 0) { //child process
CLOSESOCKET(socket_listen);
while(1) {
char read[1024];
int bytes_received = recv(socket_client, read, 1024, 0);
if (bytes_received < 1) {
CLOSESOCKET(socket_client);
exit(0);
}
int j;
for (j = 0; j < bytes_received; ++j)
read[j] = toupper(read[j]);
send(socket_client, read, bytes_received, 0);
}
}
CLOSESOCKET(socket_client);
} //while(1)
printf("Closing listening socket...\n");
CLOSESOCKET(socket_listen);
printf("Finished.\n");
return 0;
}
  • Client
#define _POSIX_C_SOURCE 200112L
#define _DEFAULT_SOURCE
#define _BSD_SOURCE
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define ISVALIDSOCKET(s) ((s) >= 0)
#define CLOSESOCKET(s) close(s)
#define SOCKET int
#define GETSOCKETERRNO() (errno)
int main() {
printf("Connecting to server...\n");
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo *peer_address;
if (getaddrinfo("127.0.0.1", "3030", &hints, &peer_address)) {
fprintf(stderr, "getaddrinfo() failed.\n");
return 1;
}
SOCKET socket_peer;
socket_peer = socket(peer_address->ai_family,
peer_address->ai_socktype, peer_address->ai_protocol);
if (!ISVALIDSOCKET(socket_peer)) {
fprintf(stderr, "socket() failed. (%d)\n", GETSOCKETERRNO());
return 1;
}
if (connect(socket_peer,
peer_address->ai_addr, peer_address->ai_addrlen)) {
fprintf(stderr, "connect() failed. (%d)\n", GETSOCKETERRNO());
return 1;
}
freeaddrinfo(peer_address);
printf("Connected. Type messages to send (Ctrl+C to quit):\n");
fd_set master;
FD_ZERO(&master);
FD_SET(socket_peer, &master);
FD_SET(0, &master); // stdin
SOCKET max_socket = socket_peer;
while(1) {
fd_set reads;
reads = master;
if (select(max_socket+1, &reads, 0, 0, 0) < 0) {
fprintf(stderr, "select() failed. (%d)\n", GETSOCKETERRNO());
return 1;
}
if (FD_ISSET(socket_peer, &reads)) {
char read[4096];
int bytes_received = recv(socket_peer, read, 4096, 0);
if (bytes_received < 1) {
printf("Connection closed by peer.\n");
break;
}
printf("Received: %.*s", bytes_received, read);
}
if (FD_ISSET(0, &reads)) {
char read[4096];
if (!fgets(read, 4096, stdin)) break;
printf("Sending: %s", read);
int bytes_sent = send(socket_peer, read, strlen(read), 0);
if (bytes_sent < 1) {
printf("send() failed.\n");
break;
}
}
}
printf("Closing socket...\n");
CLOSESOCKET(socket_peer);
printf("Finished.\n");
return 0;
}

OUTPUT

  • Sever
Terminal window
c@c:~/cos3105/network_server$ make run
gcc -Wall -Wextra -std=c99 -c src/server.c -o obj/server.o
g++ -o bin/server obj/server.o
./bin/server
Configuring local address...
Creating socket...
Binding socket to local address...
Listening...
Waiting for connections...
New connection from 127.0.0.1
  • Client
Terminal window
c@c:~/cos3105/network_client$ make run
./bin/client
Connecting to server...
Connected. Type messages to send (Ctrl+C to quit):
test
Sending: test
Received: TEST
AAAA
Sending: AAAA
Received: AAAA
  • Server
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
struct rpc_data {
int a, b, result;
};
int main() {
int server_fd, client_fd;
struct sockaddr_un addr;
struct rpc_data data;
// Create socket
server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
// Setup address
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/tmp/rpc");
unlink("/tmp/rpc");
// Bind and listen
bind(server_fd, (struct sockaddr*)&addr, sizeof(addr));
listen(server_fd, 1);
printf("RPC Server ready\n");
// Accept client
client_fd = accept(server_fd, NULL, NULL);
// Receive parameters
recv(client_fd, &data, sizeof(data), 0);
printf("Received: %d + %d\n", data.a, data.b);
// Do calculation (this is the "remote" function)
data.result = data.a + data.b;
// Send result back
send(client_fd, &data, sizeof(data), 0);
printf("Sent result: %d\n", data.result);
close(client_fd);
close(server_fd);
unlink("/tmp/rpc");
return 0;
}

OUTPUT

Terminal window
c@c:~/cos3105$ ./rpc_server
RPC Server ready
Received: 10 + 5
Sent result: 15
  • Client
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
struct rpc_data {
int a, b, result;
};
// This function looks local but actually calls remote server
int remote_add(int x, int y) {
int sockfd;
struct sockaddr_un addr;
struct rpc_data data;
// Connect to server
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/tmp/rpc");
connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));
// Send parameters
data.a = x;
data.b = y;
send(sockfd, &data, sizeof(data), 0);
// Get result
recv(sockfd, &data, sizeof(data), 0);
close(sockfd);
return data.result;
}
int main() {
printf("RPC Client\n");
// This looks like a normal function call!
int result = remote_add(10, 5);
printf("10 + 5 = %d\n", result);
return 0;
}

OUTPUT

Terminal window
c@c:~/cos3105$ ./rpc_client
RPC Client
10 + 5 = 15
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdbool.h>
#define ARRAY_SIZE 5
struct Item {
int buffers[ARRAY_SIZE];
int in;
int out;
};
int main() {
// Create shared array
struct Item *shared_items = mmap(NULL, sizeof(struct Item),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (fork() == 0) {
// Child process
int value = 10;
while(true){
while((shared_items->in + 1) % ARRAY_SIZE == shared_items->out);
printf("produce: %d\n", value);
shared_items->buffers[shared_items->in] = value;
shared_items->in = (shared_items->in + 1) % ARRAY_SIZE;
value+=10;
sleep(1);
}
}
else {
// Parent process
sleep(1);
while(true){
while(shared_items->in == shared_items->out);
int value = shared_items->buffers[shared_items->out];
printf("consume: %d\n", value);
shared_items->out = (shared_items->out + 1) % ARRAY_SIZE;
sleep(1);
}
wait(NULL); // Wait for child
munmap(shared_items, sizeof(struct Item));
}
return 0;
}
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdbool.h>
#define ARRAY_SIZE 5
struct Item {
int buffers[ARRAY_SIZE];
int in;
int out;
int counter;
};
int main() {
// Create shared array
struct Item *shared_items = mmap(NULL, sizeof(struct Item),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (fork() == 0) {
// Child process
int value = 10;
while(true){
while(shared_items->counter == ARRAY_SIZE);
printf("produce: %d\n", value);
shared_items->buffers[shared_items->in] = value;
shared_items->in = (shared_items->in + 1) % ARRAY_SIZE;
shared_items->counter = shared_items->counter+1;
value+=10;
// sleep(3);
}
}
else {
// Parent process
// sleep(1);
while(true){
while(shared_items->counter == 0);
int value = shared_items->buffers[shared_items->out];
printf("consume: %d\n", value);
shared_items->out = (shared_items->out + 1) % ARRAY_SIZE;
shared_items->counter = shared_items->counter-1;
// sleep(1);
}
wait(NULL); // Wait for child
munmap(shared_items, sizeof(struct Item));
}
return 0;
}

OUTPUT

Terminal window
consume: 1042170
produce: 1042210
consume: 1042180
produce: 1042220
consume: 1042190
produce: 1042230
consume: 1042200
produce: 1042240
consume: 1042210
produce: 1042250
consume: 1042220
produce: 1042260
consume: 1042230
produce: 1042270
consume: 1042240
produce: 1042280
consume: 1042250