350 likes | 462 Views
Module #3 POSIX programming- Shm. Lecture 4. Unix Interprocess Comm. Unix is rich in inter process communication mechanism. These are: Signal Pipe FIFO (named pipe) IPC Message queues Semaphore Shared memory (fastest). IPC.
E N D
Module #3POSIX programming- Shm Lecture 4
Unix Interprocess Comm • Unix is rich in inter process communication mechanism. These are: • Signal • Pipe • FIFO (named pipe) • IPC • Message queues • Semaphore • Shared memory (fastest)
IPC • An elegant means of interprocess communication mechanisms provided by the group of techniques called IPC IPCs are also directly managed by kernel • Using IPCs, concurrent processes can interact in a client-server manner (eg: database server) or peer-to-peer manner( eg: email server) • Within a machine each of these resources is identified by an integer called “KEY”, ie the key is used as the sharing anchor. • Each resource belongs to an owner and has access rights • There are two shell commands to check on them: • ipcs (similar to ls) –list down all the IPC resources currently available • Ipcrm (similar to rm) – remove the IPC resource given as argument in the command
ipcs command [staff@localhost staff]$ ipcs -------Shared Memory segments--------- Key shmid owner perms bytes nattch status 0x0000 163841 staff 600 339216 2 dest 0x0000 196610 staff 600 393216 2 dest ……Semaphore Arraya………………. Key semid owner perms nsems …….message queues-------------------- Key msqid owner perms used-bytes messages
IPC mechanisms <ipc.h> • Messages - a tech. which allows processes on the same machine to exchange formatted message • Semaphore – a set of wide variables which can be modified and used by processes on the same machine to synch execution. • Shared memory - a common region of virtual memory( part of RAM), shared by multiple processes on the same machine, such that the data in the shared memory can be directly read and modified by other processes
IPC generic operations • All three IPCs share a set of generic operations: • get operation : to create or gain access to resource. The sys call returns a facility identifier to be used in calls to other IPC routines, • Control oper: to get status or set ctrl values • Specific oper: to do more specific task based on the type of resource.
Common data structure • Note the common definitions for constants across these mechanisms used in their respective sys calls. • The values of IPC_CREAT and others like it are defined in <sys/ipc.h> • #define IPC_CREAT 0x1000 • #define IPC_EXCL 0x2000 • These constant are usually bit-wise operated, eg: IPC_CREAT | “0600” is bitwise OR-ed to achieve the required access rights
Unix Interprocess Comm • Unix is rich in inter process communication mechanism. These are: • Signal • Pipe • FIFO (named pipe) • IPC • Message queues • Semaphore • Shared memory (fastest)
Shared Memory ( shm) Shared Region memory Process 1 Process 2
Shm …what is it? • Shared Memory is memory that can be seen by more than one process. Normally, when you fork a process, the 2 processes don't access the same memory • You acquire a shared memory segment by making a call that looks like:shmid = shmget(key, size/* in bytes */, flags); • The fastest form of inter- process communication involving data
Shm Concepts • the key must be unique on a given host • the key can be IPC_PRIVATE if you want shared memory that isn't associated with any key. • The flags include permissions and can contain IPC_CREAT and IPC_EXCL. IPC_CREAT creates a shared memory segment if it doesn't already exist. If IPC_EXCL is included with IPC_CREAT then it is considered a failure if the shared memory does already exist. Some valid flag combinations are:06600660 | IPC_CREAT0600 | IPC_CREAT | IPC_EXCL • A negative return code indicates failure and you should check errno (using perror or strerror).
…cont • Normally, your program should free up any shared memory that it allocates. However, if your program crashes, your shared memory doesn't automatically get freed up. It stays around and can be seen with the ipcs command. • You can free up your shared memory with a command like:ipcrm shm xxxxx • The script below will destroy all of your shared memory segments:
…/ shm • The shm (segment) can be shared by many processes, and a process may access many shared segments • When a shm is identified, it is initially outside the address space of a process. The process has to execute sys calls to include it into the space
shmat • Once you have a shared memory segment id (shmid), then you next need to to map the memory into your address space. Normally, this should be done with the command • char * shm_addr; • shm_addr = shmat( shmid, NULL, 0); • if (shm_addr == (char *) -1)you have an error. • If you want READ_ONLY access to your shared memory, you can set the third parameter to SHM_RDONLY. • It is also possible to set the second parameter to the address where you want your shared memory to show up. I would recommend that you don't use this option. The reason people might want this is because they have pointers in their shared memory.
…/shm • System calls involved are: • shmget to translate a shm KEY to a segment-ID. • shmat to amap/attach a segment to the process address space • shmdt to detach a segment from the process address space. • shmctl to destroy a segment when it is no longer required.
…cont • When you get back a good shm_addr, remember it and normally you will want to caste it to data type of your shared memory. Usually its a good idea to create a structthat contains your shared memory. In this way, you can get the compiler to do most of the work computing sizes and figuring out pointers, etc.
Shm-reader process #include <stdio.h> #include “sys/ipc.h” #include “sys/shm.h” #define KEY 1000 /* key for the shm */ main() { int descr, *p, i; printf((“shm: Start of main of “ readerprocess…\n”); //request shared memory of size 10 x integer size descr= shmget(KEY,10*sizeof(int), IPC_CREAT|0660); p = (int *)shmat(descr, NULL,0); while(1){ sleep(2); for(i=0; i<10; i++) { printf(“shm: value of p[%d]= %d\n”,I,p[i]); } } }
Shm –writer process # include <stdio.h> # include “sys/ipc.h” # include “sys/shm.h” # define KEY 1000 /* key for the shm */ main() { int descr, i,g ; int *p; printf(“shm: Start of main of “ writer process…\n”); //request shared memory of size 10 x integer size descr = shmget (KEY,10*sizeof ( int ), IPC_CREAT|0660); p = (int *) shmat(descr, NULL,0); g=0; while(1) { sleep(1); for(i=0; i<10; i++) { p[i] =g; g=g+1; } } }
Shm-reader process #include <stdio.h> #include “sys/ipc.h” #include “sys/shm.h” #define KEY 1000 /* key for the shm */ main() { intdescr, *p, i; printf((“shm: Start of main of “ readerprocess…\n”); //request shared memory of size 10 x integer size //request shared memory of size 10 x integer size descr = shmget(KEY,10*sizeof ( int ), IPC_CREAT|0660); p = (int *) shmat(descr, NULL,0); while(1){ sleep(2); for(i=0; i<10; i++) { printf(“shm: value of p[%d]= %d\n”,I,p[i]); } } } Real Time System
Output • It’s time to think • Explain how does the code behave??
Exercise • Modify the program so that you can accommodate a different data strucuture for the shared memory region, for example which consist of: An array of integers of size 10, followed by an array of characters of size 20 and followed by an array of double of size 5.
UNIX IPC mechanism • Unix is rich in inter process communication mechanism. These are: • Signal • Pipe • FIFO (named pipe) • IPC • Message queues • Semaphore • Shared memory (fastest)
Concept of ‘messages’ • Allow sending and receiving of messages among multiple processes, analogy: having a central mailbox in a building where many people can deposit and receive mails from the box. • Just like all messages have receipient address, each message has an integer mesage type assigned by the sender, so that receipient process can selectively receive messages based on the type. • Messages stored in queue are permanent, even when no proces is referencing the queue. A message is remove only when a process explicitly removes it from the queue. • There can be many message queues, which are referred and used by many processes, and this reflects the dynamism for interprocess comm using this technique.
Kernel data structure for message queue msg3 msg2 msg1 record Message table
Sending and Retrieving messages • When a process sends a message to the queue, the kernel creates a new message record and puts it at the end of the list. • When process retrieve a message, the kernel copies the content to his virtual address, then discard the message from the queue. Retrieval can be: • Retrieval the oldest regardless of message type • Retrieve the message with ID matches the one requested by the process. If there are many take the oldest. • Retrieve a message whose type is lowest among those which are less than or equal.
…/Sending and retrieving messages • If there is no message to be read which satisfies the retrieval criteria, the process will be blocked, unless specified otherwise( IPC_NOWAIT flag is set, and returns a failure). • There are also system imposed limits on manipulation of messages ,eg: MSGMNI = max no. of queues that can exist, MSGMAX = max size of a message etc. • Any system call that attempts to trangress these limits will fail.
Message APIs • msgget – open and create if needed, a message queue for acces • msgsend – send a message toamessage queue • msgrcv – retrieve a message • msgctrl – manipulate the control data of a message queue • These are analogous to : open, read, write,stat,unlink, chmod etc for files
Message Q Buf The structure at the basis of the system describing a message is called msgbuf ;it is declared in linux/msg.h /* message buffer for msgsnd and msgrcv calls */ struct msgbuf { long mtype; /* type of message */ char mtext[1]; /* message text */ };
struct message { long mtype; /* message type */ long sender; /* sender id */ long receiver; /* receiver id */ struct info data; /* message content */ ... };
Sampel Code #include <stdio.h> #include <stdlib.h> #include <linux/ipc.h> #include <linux/msg.h> /* Redefines the struct msgbuf */ typedef struct mymsgbuf { long mtype; int int_num; float float_num; char ch; } mess_t;
…cont int main() { int qid; key_t msgkey; mess_t sent; mess_t received; int length; /* Initializes the seed of the pseudo-random number generator */ srand (time (0)); /* Length of the message */ length = sizeof(mess_t) - sizeof(long); msgkey = ftok(".",'m');
/* Creates the queue*/ qid = msgget(msgkey, IPC_CREAT | 0660); printf("QID = %d\n", qid); /* Builds a message */ sent.mtype = 1; sent.int_num = rand(); sent.float_num = (float)(rand())/3; sent.ch = 'f'; /* Sends the message */ msgsnd(qid, &sent, length, 0); printf("MESSAGE SENT...\n");
/* Receives the message */ msgrcv(qid, &received, length, sent.mtype, 0); printf("MESSAGE RECEIVED...\n"); /* Controls that received and sent messages are equal */ printf("Integer number = %d (sent %d) -- ", received.int_num, sent.int_num); if(received.int_num == sent.int_num) printf(" OK\n"); else printf("ERROR\n"); printf("Float number = %f sent %f -- ", received.float_num, sent.float_num); if(received.float_num == sent.float_num) printf(" OK\n"); else printf("ERROR\n"); printf("Char = %c (sent %c) -- ", received.ch, sent.ch); if(received.ch == sent.ch) printf(" OK\n"); else printf("ERROR\n");
/* Destroys the queue */ msgctl(qid, IPC_RMID, 0);