목차
1. 공유 메모리란" >1. 공유 메모리란
2. 공유 메모리의 사용" >2. 공유 메모리의 사용
三、使用共享内存进行进程间通信" >三、使用共享内存进行进程间通信
시스템 튜토리얼 리눅스 Linux 프로세스 간 통신을 위한 효율적인 방법: 공유 메모리 사용

Linux 프로세스 간 통신을 위한 효율적인 방법: 공유 메모리 사용

Feb 11, 2024 pm 07:00 PM
linux 리눅스 튜토리얼 리눅스 시스템 리눅스 명령 쉘 스크립트 동기화 메커니즘 임베디드리눅스 리눅스 시작하기 리눅스 학습

다음에서는 공유 메모리를 사용하는 또 다른 프로세스 간 통신 방법에 대해 설명합니다.

1. 공유 메모리란

이름에서 알 수 있듯이 공유 메모리를 사용하면 관련되지 않은 두 프로세스가 동일한 논리 메모리에 액세스할 수 있습니다. 공유 메모리는 실행 중인 두 프로세스 간에 데이터를 공유하고 전송하는 매우 효율적인 방법입니다. 서로 다른 프로세스 간에 공유되는 메모리는 일반적으로 물리적 메모리의 동일한 세그먼트로 배열됩니다. 프로세스는 공유 메모리의 동일한 세그먼트를 자신의 주소 공간에 연결할 수 있으며 모든 프로세스는 마치 C 언어 함수 malloc을 사용하여 할당된 메모리인 것처럼 공유 메모리의 주소에 액세스할 수 있습니다. 그리고 프로세스가 공유 메모리에 데이터를 쓰는 경우 변경 사항은 공유 메모리의 동일한 세그먼트에 액세스할 수 있는 다른 프로세스에 즉시 영향을 미칩니다.

Linux 进程间通信的一种高效方法:使用共享内存

특별 알림: 공유 메모리는 동기화 메커니즘을 제공하지 않습니다. 즉, 첫 번째 프로세스가 공유 메모리에 쓰기를 마치기 전에 두 번째 프로세스가 이를 읽기 시작하는 것을 방지하는 자동 메커니즘이 없습니다. 따라서 공유 메모리에 대한 액세스를 동기화하려면 일반적으로 앞서 언급한 세마포어와 같은 다른 메커니즘을 사용해야 합니다. 세마포어에 대한 자세한 내용은 내 다른 기사인 Linux 프로세스 간 통신 - 세마포어 사용

을 참조하세요.

2. 공유 메모리의 사용

세마포어와 마찬가지로 Linux도 공유 메모리 사용을 위한 기능적 인터페이스 세트를 제공하며 공유 공존을 사용하는 인터페이스는 세마포어와 매우 유사하며 세마포어를 사용하는 인터페이스보다 간단합니다. 헤더 파일 sys/shm.h에 선언되어 있습니다.

1.shmget 기능

이 함수는 공유 메모리를 생성하는 데 사용되며 프로토타입은 다음과 같습니다.

  1. int shmget(key_t 키, size_t 크기, int shmflg);

첫 번째 매개변수는 세마포어의 semget 함수와 동일합니다. 프로그램은 공유 메모리 세그먼트의 이름을 효과적으로 지정하는 매개변수 키(0이 아닌 정수)를 제공해야 합니다. 후속 공유 메모리 기능에 사용되는 키와 관련된 메모리 식별자(음수가 아닌 정수)입니다. 호출이 실패하고 -1을 반환합니다.

관련되지 않은 프로세스는 프로그램이 사용할 수 있는 리소스를 나타내는 이 함수의 반환 값을 통해 동일한 공유 메모리에 액세스할 수 있습니다. 프로그램은 먼저 shmget 함수를 호출하고 키를 제공합니다. 그런 다음 시스템은 해당 공유 메모리 식별자(shmget 함수의 반환 값)를 생성합니다. shmget 함수만 세마포 키를 직접 사용하고 다른 모든 세마포 함수는 semget 함수에서 반환된 세마포 식별자를 사용합니다.

두 번째 매개변수인 size는 공유할 메모리 용량을 바이트 단위로 지정합니다

세 번째 매개변수 shmflg는 권한 플래그입니다. 해당 기능은 open 함수의 모드 매개변수와 동일합니다. 키가 존재하지 않을 때 해당 공유 메모리를 생성하려면 IPC_CREAT를 사용하거나 작업하면 됩니다. . 공유 메모리의 권한 플래그는 파일의 읽기 및 쓰기 권한과 동일합니다. 예를 들어 0644는 프로세스가 생성한 공유 메모리를 해당 프로세스가 소유한 공유 메모리에 읽고 쓸 수 있다는 의미입니다. 동시에 다른 사용자는 공유 메모리를 읽을 수만 있는 프로세스를 생성합니다.

2. shmat 기능

공유 메모리가 처음 생성되면 어떤 프로세스에서도 접근할 수 없습니다. shmat 함수의 기능은 공유 메모리에 대한 접근을 시작하고 공유 메모리를 현재 프로세스의 주소 공간에 연결하는 것입니다. 프로토타입은 다음과 같습니다:

  1. 으아아아

첫 번째 매개변수 shm_id는 shmget 함수에서 반환된 공유 메모리 ID입니다.

두 번째 매개변수 shm_addr은 공유 메모리가 현재 프로세스에 연결된 주소 위치를 지정합니다. 이는 일반적으로 비어 있으며 시스템이 공유 메모리의 주소를 선택할 수 있음을 나타냅니다.

세 번째 매개변수인 shm_flg는 플래그 비트 세트이며 일반적으로 0입니다.

호출이 성공하면 공유 메모리의 첫 번째 바이트에 대한 포인터가 반환됩니다. 호출이 실패하면 -1이 반환됩니다.

3.shmdt 기능

이 함수는 현재 프로세스에서 공유 메모리를 분리하는 데 사용됩니다. 공유 메모리를 분리해도 공유 메모리가 삭제되지는 않으며 단지 현재 프로세스에서 공유 메모리를 더 이상 사용할 수 없게 됩니다. 프로토타입은 다음과 같습니다:

으아아아

shmaddr 매개변수는 shmat 함수가 반환하는 주소 포인터입니다. 호출이 성공하면 0을 반환하고 실패하면 -1을 반환합니다.

4. shmctl 기능

세마포어의 semctl 함수와 동일하며, 공유 메모리를 제어하는 ​​데 사용됩니다. 프로토타입은 다음과 같습니다.

  1. **int** shmctl(**int** shm_id, **int** command, **struct** shmid_ds *buf); 
    
    로그인 후 복사

第一个参数,shm_id是shmget函数返回的共享内存标识符。

第二个参数,command是要采取的操作,它可以取下面的三个值 :

IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。

IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值

IPC_RMID:删除共享内存段

第三个参数,buf是一个结构指针,它指向共享内存模式和访问权限的结构。

shmid_ds结构至少包括以下成员:

1. struct** shmid_ds 
2. { 
3.   uid_t shm_perm.uid; 
4.   uid_t shm_perm.gid; 
5.   mode_t shm_perm.mode; 
6. }; 
로그인 후 복사

三、使用共享内存进行进程间通信

说了这么多,又到了实战的时候了。下面就以两个不相关的进程来说明进程间如何通过共享内存来进行通信。其中一个文件shmread.c创建共享内存,并读取其中的信息,另一个文件shmwrite.c向共享内存中写入数据。为了方便操作和数据结构的统一,为这两个文件定义了相同的数据结构,定义在文件shmdata.c中。结构shared_use_st中的written作为一个可读或可写的标志,非0:表示可读,0表示可写,text则是内存中的文件。

shmdata.h的源代码如下:

1. \#ifndef _SHMDATA_H_HEADER 
2. \#define _SHMDATA_H_HEADER 
3.  
4. \#define TEXT_SZ 2048 
5.  
6. **struct** shared_use_st 
7. { 
8.   **int** written;//作为一个标志,非0:表示可读,0表示可写 
9.   **char** text[TEXT_SZ];//记录写入和读取的文本 
10. }; 
11.  
12. \#endif 
로그인 후 복사

源文件shmread.c的源代码如下:

  1. 1. \#include  
    2. \#include  
    3. \#include  
    4. \#include  
    5. \#include "shmdata.h" 
    6.  
    7. **int** main() 
    8. { 
    9.   **int** running = 1;//程序是否继续运行的标志 
    10.   **void** *shm = NULL;//分配的共享内存的原始首地址 
    11.   **struct** shared_use_st *shared;//指向shm 
    12.   **int** shmid;//共享内存标识符 
    13.   //创建共享内存 
    14.   shmid = shmget((key_t)1234, **sizeof**(**struct** shared_use_st), 0666|IPC_CREAT); 
    15.   **if**(shmid == -1) 
    16.   { 
    17. ​    fprintf(stderr, "shmget failed\n"); 
    18. ​    exit(EXIT_FAILURE); 
    19.   } 
    20.   //将共享内存连接到当前进程的地址空间 
    21.   shm = shmat(shmid, 0, 0); 
    22.   **if**(shm == (**void***)-1) 
    23.   { 
    24. ​    fprintf(stderr, "shmat failed\n"); 
    25. ​    exit(EXIT_FAILURE); 
    26.   } 
    27.   printf("\nMemory attached at %X\n", (**int**)shm); 
    28.   //设置共享内存 
    29.   shared = (**struct** shared_use_st*)shm; 
    30.   shared->written = 0; 
    31.   **while**(running)//读取共享内存中的数据 
    32.   { 
    33. ​    //没有进程向共享内存定数据有数据可读取 
    34. ​    **if**(shared->written != 0) 
    35. ​    { 
    36. ​      printf("You wrote: %s", shared->text); 
    37. ​      sleep(rand() % 3); 
    38. ​      //读取完数据,设置written使共享内存段可写 
    39. ​      shared->written = 0; 
    40. ​      //输入了end,退出循环(程序) 
    41. ​      **if**(strncmp(shared->text, "end", 3) == 0) 
    42. ​        running = 0; 
    43. ​    } 
    44. ​    **else**//有其他进程在写数据,不能读取数据 
    45. ​      sleep(1); 
    46.   } 
    47.   //把共享内存从当前进程中分离 
    48.   **if**(shmdt(shm) == -1) 
    49.   { 
    50. ​    fprintf(stderr, "shmdt failed\n"); 
    51. ​    exit(EXIT_FAILURE); 
    52.   } 
    53.   //删除共享内存 
    54.   **if**(shmctl(shmid, IPC_RMID, 0) == -1) 
    55.   { 
    56. ​    fprintf(stderr, "shmctl(IPC_RMID) failed\n"); 
    57. ​    exit(EXIT_FAILURE); 
    58.   } 
    59.   exit(EXIT_SUCCESS); 
    60. } 
    
    로그인 후 복사

源文件shmwrite.c的源代码如下:

1. \#include  
2. \#include  
3. \#include  
4. \#include  
5. \#include  
6. \#include "shmdata.h" 
7.  
8. **int** main() 
9. { 
10.   **int** running = 1; 
11.   **void** *shm = NULL; 
12.   **struct** shared_use_st *shared = NULL; 
13.   **char** buffer[BUFSIZ + 1];//用于保存输入的文本 
14.   **int** shmid; 
15.   //创建共享内存 
16.   shmid = shmget((key_t)1234, **sizeof**(**struct** shared_use_st), 0666|IPC_CREAT); 
17.   **if**(shmid == -1) 
18.   { 
19. ​    fprintf(stderr, "shmget failed\n"); 
20. ​    exit(EXIT_FAILURE); 
21.   } 
22.   //将共享内存连接到当前进程的地址空间 
23.   shm = shmat(shmid, (**void***)0, 0); 
24.   **if**(shm == (**void***)-1) 
25.   { 
26. ​    fprintf(stderr, "shmat failed\n"); 
27. ​    exit(EXIT_FAILURE); 
28.   } 
29.   printf("Memory attached at %X\n", (**int**)shm); 
30.   //设置共享内存 
31.   shared = (**struct** shared_use_st*)shm; 
32.   **while**(running)//向共享内存中写数据 
33.   { 
34. ​    //数据还没有被读取,则等待数据被读取,不能向共享内存中写入文本 
35. ​    **while**(shared->written == 1) 
36. ​    { 
37. ​      sleep(1); 
38. ​      printf("Waiting...\n"); 
39. ​    } 
40. ​    //向共享内存中写入数据 
41. ​    printf("Enter some text: "); 
42. ​    fgets(buffer, BUFSIZ, stdin); 
43. ​    strncpy(shared->text, buffer, TEXT_SZ); 
44. ​    //写完数据,设置written使共享内存段可读 
45. ​    shared->written = 1; 
46. ​    //输入了end,退出循环(程序) 
47. ​    **if**(strncmp(buffer, "end", 3) == 0) 
48. ​      running = 0; 
49.   } 
50.   //把共享内存从当前进程中分离 
51.   **if**(shmdt(shm) == -1) 
52.   { 
53. ​    fprintf(stderr, "shmdt failed\n"); 
54. ​    exit(EXIT_FAILURE); 
55.   } 
56.   sleep(2); 
57.   exit(EXIT_SUCCESS); 
58. } 
로그인 후 복사

再来看看运行的结果:

分析:

1、程序shmread创建共享内存,然后将它连接到自己的地址空间。在共享内存的开始处使用了一个结构struct_use_st。该结构中有个标志written,当共享内存中有其他进程向它写入数据时,共享内存中的written被设置为0,程序等待。当它不为0时,表示没有进程对共享内存写入数据,程序就从共享内存中读取数据并输出,然后重置设置共享内存中的written为0,即让其可被shmwrite进程写入数据。

2、程序shmwrite取得共享内存并连接到自己的地址空间中。检查共享内存中的written,是否为0,若不是,表示共享内存中的数据还没有被完,则等待其他进程读取完成,并提示用户等待。若共享内存的written为0,表示没有其他进程对共享内存进行读取,则提示用户输入文本,并再次设置共享内存中的written为1,表示写完成,其他进程可对共享内存进行读操作。

四、关于前面的例子的安全性讨论

这个程序是不安全的,当有多个程序同时向共享内存中读写数据时,问题就会出现。可能你会认为,可以改变一下written的使用方式,例如,只有当written为0时进程才可以向共享内存写入数据,而当一个进程只有在written不为0时才能对其进行读取,同时把written进行加1操作,读取完后进行减1操作。这就有点像文件锁中的读写锁的功能。咋看之下,它似乎能行得通。但是这都不是原子操作,所以这种做法是行不能的。试想当written为0时,如果有两个进程同时访问共享内存,它们就会发现written为0,于是两个进程都对其进行写操作,显然不行。当written为1时,有两个进程同时对共享内存进行读操作时也是如些,当这两个进程都读取完是,written就变成了-1.

要想让程序安全地执行,就要有一种进程同步的进制,保证在进入临界区的操作是原子操作。例如,可以使用前面所讲的信号量来进行进程的同步。因为信号量的操作都是原子性的。

五、使用共享内存的优缺点

1、优点:我们可以看到使用共享内存进行进程间的通信真的是非常方便,而且函数的接口也简单,数据的共享还使进程间的数据不用传送,而是直接访问内存,也加快了程序的效率。同时,它也不像匿名管道那样要求通信的进程有一定的父子关系。

2、缺点:共享内存没有提供同步的机制,这使得我们在使用共享内存进行进程间通信时,往往要借助其他的手段来进行进程间的同步工作。

위 내용은 Linux 프로세스 간 통신을 위한 효율적인 방법: 공유 메모리 사용의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

C 언어로 멀티 스레딩을 구현하는 4 가지 방법 C 언어로 멀티 스레딩을 구현하는 4 가지 방법 Apr 03, 2025 pm 03:00 PM

언어의 멀티 스레딩은 프로그램 효율성을 크게 향상시킬 수 있습니다. C 언어에서 멀티 스레딩을 구현하는 4 가지 주요 방법이 있습니다. 독립 프로세스 생성 : 여러 독립적으로 실행되는 프로세스 생성, 각 프로세스에는 자체 메모리 공간이 있습니다. 의사-다일리트 레딩 : 동일한 메모리 공간을 공유하고 교대로 실행하는 프로세스에서 여러 실행 스트림을 만듭니다. 멀티 스레드 라이브러리 : PTHREADS와 같은 멀티 스레드 라이브러리를 사용하여 스레드를 만들고 관리하여 풍부한 스레드 작동 기능을 제공합니다. COROUTINE : 작업을 작은 하위 작업으로 나누고 차례로 실행하는 가벼운 다중 스레드 구현.

Web.xml을 열는 방법 Web.xml을 열는 방법 Apr 03, 2025 am 06:51 AM

Web.xml 파일을 열려면 다음 방법을 사용할 수 있습니다. 텍스트 편집기 (예 : 메모장 또는 문자 메시지)를 사용하여 통합 개발 환경 (예 : Eclipse 또는 NetBeans)을 사용하여 명령을 편집하십시오 (Windows : Notepad Web.xml; Mac/Linux : Open -A Texted web.xml).

Linux 시스템에서 Python 통역사를 삭제할 수 있습니까? Linux 시스템에서 Python 통역사를 삭제할 수 있습니까? Apr 02, 2025 am 07:00 AM

Linux 시스템과 함께 제공되는 Python 통역사를 제거하는 문제와 관련하여 많은 Linux 배포판이 설치 될 때 Python 통역사를 사전 설치하고 패키지 관리자를 사용하지 않습니다 ...

가장 잘 사용되는 Linux는 무엇입니까? 가장 잘 사용되는 Linux는 무엇입니까? Apr 03, 2025 am 12:11 AM

Linux는 서버 관리, 임베디드 시스템 및 데스크탑 환경으로 사용되는 것이 가장 좋습니다. 1) 서버 관리에서 Linux는 웹 사이트, 데이터베이스 및 응용 프로그램을 호스팅하는 데 사용되어 안정성과 안정성을 제공합니다. 2) 임베디드 시스템에서 Linux는 유연성과 안정성으로 인해 스마트 홈 및 자동차 전자 시스템에서 널리 사용됩니다. 3) 데스크탑 환경에서 Linux는 풍부한 응용 프로그램과 효율적인 성능을 제공합니다.

데비안 하프 (Debian Hadoop)의 호환성은 어떻습니까? 데비안 하프 (Debian Hadoop)의 호환성은 어떻습니까? Apr 02, 2025 am 08:42 AM

Debianlinux는 안정성과 보안으로 유명하며 서버, 개발 및 데스크탑 환경에서 널리 사용됩니다. 현재 Debian 및 Hadoop과 직접 호환성에 대한 공식 지침이 부족하지만이 기사에서는 Debian 시스템에 Hadoop를 배포하는 방법을 안내합니다. 데비안 시스템 요구 사항 : Hadoop 구성을 시작하기 전에 Debian 시스템이 Hadoop의 최소 작동 요구 사항을 충족하는지 확인하십시오. 여기에는 필요한 JAVA 런타임 환경 (JRE) 및 Hadoop 패키지 설치가 포함됩니다. Hadoop 배포 단계 : 다운로드 및 unzip hadoop : 공식 Apachehadoop 웹 사이트에서 필요한 Hadoop 버전을 다운로드하여 해결하십시오.

GO를 사용하여 Oracle 데이터베이스에 연결할 때 Oracle 클라이언트를 설치해야합니까? GO를 사용하여 Oracle 데이터베이스에 연결할 때 Oracle 클라이언트를 설치해야합니까? Apr 02, 2025 pm 03:48 PM

GO를 사용하여 Oracle 데이터베이스에 연결할 때 Oracle 클라이언트를 설치해야합니까? GO에서 개발할 때 Oracle 데이터베이스에 연결하는 것이 일반적인 요구 사항입니다 ...

데비안 문자열은 여러 브라우저와 호환됩니다 데비안 문자열은 여러 브라우저와 호환됩니다 Apr 02, 2025 am 08:30 AM

"Debiantrings"는 표준 용어가 아니며 구체적인 의미는 여전히 불분명합니다. 이 기사는 브라우저 호환성에 직접 언급 할 수 없습니다. 그러나 "Debiantrings"가 Debian 시스템에서 실행되는 웹 응용 프로그램을 지칭하는 경우 브라우저 호환성은 응용 프로그램 자체의 기술 아키텍처에 따라 다릅니다. 대부분의 최신 웹 응용 프로그램은 크로스 브라우저 호환성에 전념합니다. 이는 웹 표준에 따라 웹 표준과 잘 호환 가능한 프론트 엔드 기술 (예 : HTML, CSS, JavaScript) 및 백엔드 기술 (PHP, Python, Node.js 등)을 사용하는 데 의존합니다. 응용 프로그램이 여러 브라우저와 호환되도록 개발자는 종종 브라우저 크로스 테스트를 수행하고 응답 성을 사용해야합니다.

See all articles