Linux inter-process communication-shared memory

Source: Internet
Author: User
Tags semaphore stdin

Shared memory: A piece of memory reserved by the kernel space for interprocess communication

Shared memory is one of the most efficient inter-process communication methods, because the process can read and write memory directly, does not require any data replication, in order to exchange information between processes, the kernel has set aside a memory area, this memory can be accessed by the process to map it to its own private address space, therefore, Process can directly read and write this memory without the need for data replication, which greatly improves efficiency, of course, because multiple processes share a piece of memory, it is also necessary to rely on some kind of synchronization mechanism, such as mutual exclusion lock and semaphore, etc.

(1) int shmget (key_t key, size_t size, int shmflg);

Function: Gets the ID of the shared memory segment

Parameters:
@key ipc_private or Ftok ()
@size the requested shared memory segment size [multiples of 4k]
@shmflg Ipc_creat | 0666 or Ipc_creat | Ipc_excl

return value:
Successful return ID, failure return-1

(2) void *shmat (int shmid, const void *shmaddr, int shmflg);
Function: Map shared memory to user space
Parameters:
@shmid Shared memory Segment ID
@shmaddr NULL: System Auto-complete mapping
@shmflg: shm_rdonly: Read only 0: Read and write
return value:
Successful return of mapped address, failed return (void *)-1

Exercise: A/b communicates through shared memory

b How do you know that A has already written the data?

Flag_r flag_w
-------------------------------------------------------------------------------------
| | Data (input from keyboard)
-------------------------------------------------------------------------------------

(3) int shmdt (const void *SHMADDR);
function: Undo Map
Parameters:
@shmaddr the address of the shared memory map

Note: When a process finishes, it maps shared memory and automatically revokes the mappings


(4) int shmctl (int shmid, int cmd, struct shmid_ds *buf);
Function: Control shared memory according to command
Parameters:
@shmid the ID of the shared memory segment
@cmd ipc_stat[Get Property],ipc_set[Set Property],ipc_rmid[Delete IPC Object]
@buf Save Properties
return value:
Successful return 0, failure return-1

----------------------------------------------------------------------------
Note: When we call Shmctl to delete the shared memory, it is not deleted immediately. Only if the shared memory map
The number of times is 0 to delete the shared memory object
-----------------------------------------------------------------------------

Examples are as follows:

Shm_r.c

#define SHM_SIZE 4096

typedef struct{
int Read_flag;
int Write_flag;
Char mtxt[1];//marked data storage address
}data_t;

int shm_init (const char *pathname,int ID)
{
int shmid;
key_t key;

Key = Ftok (Pathname,id);
if (Key < 0) {
fprintf (stderr, "Fail to Ftok:%s!\n", Strerror (errno));
Exit (Exit_failure);
}

Shmid = Shmget (key,shm_size,ipc_creat | 0666);
if (Shmid < 0) {
fprintf (stderr, "Fail to Shmget:%s\n", Strerror (errno));
Exit (Exit_failure);
}

return shmid;
}

void Read_shm (void *addr)
{
data_t *pdata;
pdata = (data_t *) addr;

Pdata->read_flag = 0;
Pdata->write_flag = 1;

while (1) {
if (Pdata->read_flag) {
printf ("Read:%s!\n", pdata->mtxt);
Pdata->write_flag = 1;
Pdata->read_flag = 0;
}
}

}

./a.out Pathname
int main (int argc, const char *argv[])
{
int shmid;
void *addr;

if (ARGC < 2) {
fprintf (stderr, "Usage:%s <pathname> \ n", argv[0]);
Exit (Exit_failure);
}

Shmid = Shm_init (argv[1], ' K ');
addr = (void *) Shmat (shmid,null,0);
if (addr = = (void *)-1) {
fprintf (stderr, "Fail to Shmat:%s\n", Strerror (errno));
Exit (Exit_failure);
}

Read_shm (addr);

return 0;
}

Shm_w.c

#define SHM_SIZE 4096

typedef struct{
int Read_flag;
int Write_flag;
Char mtxt[1];//marked data storage address
}data_t;

int shm_init (const char *pathname,int ID)
{
int shmid;
key_t key;

Key = Ftok (Pathname,id);
if (Key < 0) {
fprintf (stderr, "Fail to Ftok:%s!\n", Strerror (errno));
Exit (Exit_failure);
}

Shmid = Shmget (key,shm_size,ipc_creat | 0666);
if (Shmid < 0) {
fprintf (stderr, "Fail to Shmget:%s\n", Strerror (errno));
Exit (Exit_failure);
}

return shmid;
}

void Write_shm (void *addr)
{
data_t *pdata;
pdata = (data_t *) addr;

Pdata->read_flag = 0;
Pdata->write_flag = 1;

while (1) {
if (Pdata->write_flag) {
Fgets (Pdata->mtxt,shm_size-8,stdin);//Read and write flags total 8 bytes
Pdata->mtxt[strlen (Pdata->mtxt)-1] = ' + ';

Pdata->write_flag = 0;
Pdata->read_flag = 1;
}
}

}

./a.out Pathname
int main (int argc, const char *argv[])
{
int shmid;
void *addr;

if (ARGC < 2) {
fprintf (stderr, "Usage:%s <pathname> \ n", argv[0]);
Exit (Exit_failure);
}

Shmid = Shm_init (argv[1], ' K ');
addr = (void *) Shmat (shmid,null,0);
if (addr = = (void *)-1) {
fprintf (stderr, "Fail to Shmat:%s\n", Strerror (errno));
Exit (Exit_failure);
}

Write_shm (addr);

return 0;
}

Run and execute SHM_W.C

Run and execute SHM_R.C

The idea is still relatively simple

Can the above code be improved?

This code involves the knowledge of semaphores, which can be viewed: Linux interprocess communication-semaphore

First introduced:

Sem.c

Union Semun {
intval;/* 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 Init_sem_value (int sem_id,int sem_num,int value)
{
Union Semun Sem_val;

Sem_val.val = value;

if (Semctl (Sem_id,sem_num,setval,sem_val) < 0)
{
Perror ("Fail to Semctl");
Exit (Exit_failure);
}

return;
}

int Init_sems (const char *filename,int nsem)
{
key_t key;
int sem_id;

key = Ftok (filename, ' B ');
if (Key < 0) {
perror ("Fail to Ftok");
exit (exit_failure);
}

sem_id = Semget (key,nsem,ipc_creat| ipc_excl| 0666);
if (sem_id < 0)
{
//already exists
if (errno = = EEX IST)
{
//regain ID
sem_id = semget (Key,nsem,ipc_creat | 0666);

}else{
//Other error
perror ("Fail to Semget");
exit (exit_failure);
}

//Does not exist, after creation, initialize
}else{

init_ Sem_value (sem_id,0,0);//0 semaphore is initialized to 0
init_sem_value (sem_id,1,1),//1 signal is initialized to 1
 }

return sem_id;
}

void P (int sem_id,int sem_num)
{
struct SEMBUF sem;

Sem.sem_num = Sem_num;
Sem.sem_op =-1;
SEM.SEM_FLG = 0;

if (Semop (sem_id,&sem,1) < 0)
{
Perror ("Fail to Semop for p\n");
Exit (Exit_failure);
}

return;
}

void V (int sem_id,int sem_num)
{
struct SEMBUF sem;

Sem.sem_num = Sem_num;
Sem.sem_op = 1;
SEM.SEM_FLG = 0;

if (Semop (sem_id,&sem,1) < 0)
{
Perror ("Fail to Semop for v\n");
Exit (Exit_failure);
}

return;
}

SHM_R.C modified as follows:

#define SHM_SIZE 4096

int shm_init (const char *pathname,int ID)
{
int shmid;
key_t key;

Key = Ftok (Pathname,id);
if (Key < 0) {
fprintf (stderr, "Fail to Ftok:%s!\n", Strerror (errno));
Exit (Exit_failure);
}

Shmid = Shmget (key,shm_size,ipc_creat | 0666);
if (Shmid < 0) {
fprintf (stderr, "Fail to Shmget:%s\n", Strerror (errno));
Exit (Exit_failure);
}

return shmid;
}

void Read_shm (void *addr,int semid)
{
Char *pdata;
pdata = (char *) addr;


while (1) {
P Operation Read Resources
P (semid,0);//Application for reading resources

printf ("Read:%s!\n", pdata);
V Operation Write Resource
V (semid,1);//Release Write resources
}

}

./a.out Pathname
int main (int argc, const char *argv[])
{
int shmid;
int semid;
void *addr;

if (ARGC < 2) {
fprintf (stderr, "Usage:%s <pathname> \ n", argv[0]);
Exit (Exit_failure);
}

Shmid = Shm_init (argv[1], ' K ');
addr = (void *) Shmat (shmid,null,0);
if (addr = = (void *)-1) {
fprintf (stderr, "Fail to Shmat:%s\n", Strerror (errno));
Exit (Exit_failure);
}

Beacon Set
Semid = Init_sems (argv[1],2);

READ_SHM (Addr,semid);

return 0;
}

SHM_W.C modified as follows:

#define SHM_SIZE 4096

int shm_init (const char *pathname,int ID)
{
int shmid;
key_t key;

Key = Ftok (Pathname,id);
if (Key < 0) {
fprintf (stderr, "Fail to Ftok:%s!\n", Strerror (errno));
Exit (Exit_failure);
}

Shmid = Shmget (key,shm_size,ipc_creat | 0666);
if (Shmid < 0) {
fprintf (stderr, "Fail to Shmget:%s\n", Strerror (errno));
Exit (Exit_failure);
}

return shmid;
}

void Write_shm (void *addr,int semid)
{
Char *data = (char *) addr;

while (1) {
P (semid,1);
Fgets (Data,shm_size,stdin);
Data[strlen (data)-1] = ' + ';
V (semid,0);
}
}

./a.out Pathname
int main (int argc, const char *argv[])
{
int shmid;
int semid;
void *addr;

if (ARGC < 2) {
fprintf (stderr, "Usage:%s <pathname> \ n", argv[0]);
Exit (Exit_failure);
}

Shmid = Shm_init (argv[1], ' K ');
addr = (void *) Shmat (shmid,null,0);
if (addr = = (void *)-1) {
fprintf (stderr, "Fail to Shmat:%s\n", Strerror (errno));
Exit (Exit_failure);
}

Semid = Init_sems (argv[1],2);

WRITE_SHM (Addr,semid);

return 0;
}

Running results as above

Linux inter-process communication-shared memory

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.