제15장 프로세스 간 통행 15.6 XSI IPC 15.7 메시지 대기열
(1) XSI IPC라는 3가지 IPC는 다음과 같습니다.
1) 메시지 대기열
2) 신호량
3) 공유 스토리지
(2) 식별자 및 키
1) 식별자: IPC 구조를 참조하는 비 음수 정수입니다.은 IPC 객체의 내부 이름입니다.
2) 키: IPC 객체의 외부 이름입니다.여러 협력 프로세스가 동일한 IPC 객체에 모이도록 할 수 있습니다.
(3)IPC_PRIVATE 키:
새 IPC 구조를 생성할 수 있습니다.이 키를 지정하여 기존 IPC 구조를 참조할 수 없습니다.
(4) ftok 함수:
경로 이름과 항목 ID에 의해 키가 생성됩니다.
(5)ipc_perm 구조체
ipc 구조의 권한과 소유자를 규정했습니다.
(6) 구조적 제한:
XSI IPC 패브릭에는 커널을 재구성하여 변경할 수 있는 내부 한계가 있습니다.
1)sysctl 명령: 커널 구성 매개변수를 관찰, 수정합니다.
2) ipcs -l: ipc 관련 제한을 표시합니다.
(7) IPC 구조와 파이프, FIFO의 차이점:
IPC 구조는 참조 수가 없는 시스템 내에서 작동합니다.
(8) IPC 구조는 파일 시스템에 이름이 없습니다.IPC에서 파일 설명자를 사용하지 않습니다.
15.7 메시지 대기열
(1) 새 프로그램에서 메시지 대기열을 사용하지 마십시오.그것들은 결점이 있다.(15.6.4)
(2) 클라이언트 프로세스와 서버 프로세스 사이의 양방향 데이터 흐름은 메시지 대기열이나 듀플렉스 파이프를 사용할 수 있다.
15.8 신호량
(1) 여러 프로세스 간에 하나의 자원을 공유하고 신호량, 기록 자물쇠와 상호 배척량 중 하나를 사용하여 조화롭게 할 수 있다.
(2) 공유 저장소에서 상호 배척량이 가장 빠르지만 작가는 기록 자물쇠를 사용하는 두 가지 이유를 좋아한다.
1)<459>
2)<459>
15.9 공유 스토리지
(1) 공유 스토리지의 역할:
두 개 이상의 프로세스가 주어진 저장소를 공유할 수 있도록 합니다.
이것은 가장 빠른 IPC이다. 왜냐하면 데이터는 고객 프로세스와 서버 프로세스 사이에서 복제할 필요가 없기 때문이다.
(2) 공유 스토리지를 사용할 때 습득해야 할 유일한 노하우:
동기화: 쓰고 읽기.(신호량, 기록 자물쇠와 상호 배척량)
(3)
shmget 함수: 공유 메모리 식별자를 얻습니다.
shmctl 함수: 공유 메모리 세그먼트에 대해 여러 가지 작업을 수행합니다.
shmat 함수: 공유 메모리 세그먼트를 프로세스의 주소 공간에 연결합니다.
shmde 함수: 호출 프로세스를 공유 저장소에서 분리합니다.
(4) 예: 특정 시스템에 저장된 다양한 유형의 데이터의 위치 정보를 인쇄합니다.
#include "apue.h"
#include <sys/shm.h>
#define ARRAY_SIZE 40000
#define MALLOC_SIZE 100000
#define SHM_SIZE 100000
#define SHM_MODE 0600 /* user read/write */
char array[ARRAY_SIZE]; /* uninitialized data = bss */
int
main(void)
{
int shmid;
char *ptr, *shmptr;
printf("array[] from %p to %p
", (void *)&array[0],
(void *)&array[ARRAY_SIZE]);//bss
printf("stack around %p
", (void *)&shmid);
if ((ptr = malloc(MALLOC_SIZE)) == NULL)//
err_sys("malloc error");
printf("malloced from %p to %p
", (void *)ptr,
(void *)ptr+MALLOC_SIZE);
if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) < 0)
err_sys("shmget error");
if ((shmptr = shmat(shmid, 0, 0)) == (void *)-1)
err_sys("shmat error");
printf("shared memory attached from %p to %p
", (void *)shmptr,
(void *)shmptr+SHM_SIZE);
if (shmctl(shmid, IPC_RMID, 0) < 0)
err_sys("shmctl error");
exit(0);
}
(5) C 프로그램의 저장 공간 레이아웃<163>
1) 본문 세그먼트: CPU가 실행하는 기계 명령 섹션
2) 데이터 세그먼트 초기화: (데이터 세그먼트), 프로그램에 초기값을 명확하게 부여해야 하는 변수를 포함한다.
3) 초기화되지 않은 데이터 세그먼트: (bss세그먼트) 프로그램이 실행되기 전에 이 세그먼트의 데이터를 0 또는 빈 바늘로 초기화합니다.(초기화되지 않은 글로벌 변수)
4) 스택: 자동 변수와 함수 호출 때마다 필요한 정보를 저장합니다.
5) 더미: 동적 저장 분배를 진행한다.
(6) 실례: 관련 프로세스의 다른 공유 저장소를 실현하는 기술.
1)/dev/zero의 메모리 매핑 2) 스레드
#include "apue.h"
#include <fcntl.h>
#include <sys/mman.h>
#define NLOOPS 1000
#define SIZE sizeof(long) /* size of shared memory area */
static int
update(long *ptr)
{
return((*ptr)++); /* return value before increment */
}
int
main(void)
{
int fd, i, counter;
pid_t pid;
void *area;
if ((fd = open("/dev/zero", O_RDWR)) < 0)
err_sys("open error");
if ((area = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, 0)) == MAP_FAILED)
err_sys("mmap error");
close(fd); /* can close /dev/zero now that it's mapped */
TELL_WAIT();
if ((pid = fork()) < 0) {
err_sys("fork error");
} else if (pid > 0) { /* parent */
for (i = 0; i < NLOOPS; i += 2) {
if ((counter = update((long *)area)) != i)
err_quit("parent: expected %d, got %d", i, counter);
TELL_CHILD(pid);
WAIT_CHILD();
}
} else { /* child */
for (i = 1; i < NLOOPS + 1; i += 2) {
WAIT_PARENT();
if ((counter = update((long *)area)) != i)
err_quit("child: expected %d, got %d", i, counter);
TELL_PARENT(getppid());
}
}
exit(0);
}
1) open에서/dev/zero 장치 읽기/쓰기
2) mmap 함수 매핑 저장소 fd----->void*를 호출합니다.(장점: 이 함수를 호출하여 맵을 만들기 전에 실제 파일이 존재하지 않아도 됩니다.)
3)close fd 닫기
4) 모/자 프로세스에서 TELL 사용CHILD(),TELL_PARENT(),WAIT_CHILD(),WAIT_PARENT () 동기화 (이 함수들은 SIGUSR1과 SIGUSR2 신호를 통해 동기화됩니다).
#include "apue.h"
static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */
static sigset_t newmask, oldmask, zeromask;
static void
sig_usr(int signo) /* one signal handler for SIGUSR1 and SIGUSR2 */
{
sigflag = 1;
}
void
TELL_WAIT(void)
{
if (signal(SIGUSR1, sig_usr) == SIG_ERR)
err_sys("signal(SIGUSR1) error");
if (signal(SIGUSR2, sig_usr) == SIG_ERR)
err_sys("signal(SIGUSR2) error");
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGUSR1);
sigaddset(&newmask, SIGUSR2);
/* Block SIGUSR1 and SIGUSR2, and save current signal mask */
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys("SIG_BLOCK error");
}
void
TELL_PARENT(pid_t pid)
{
kill(pid, SIGUSR2); /* tell parent we're done */
}
void
WAIT_PARENT(void)
{
while (sigflag == 0)
sigsuspend(&zeromask); /* and wait for parent */
sigflag = 0;
/* Reset signal mask to original value */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
}
void
TELL_CHILD(pid_t pid)
{
kill(pid, SIGUSR1); /* tell child we're done */
}
void
WAIT_CHILD(void)
{
while (sigflag == 0)
sigsuspend(&zeromask); /* and wait for child */
sigflag = 0;
/* Reset signal mask to original value */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
}
1)
int sigsuspend(const sigset_t *mask);
신호가 도착할 때까지 임시로 신호 마스크를 바꾸고 끊습니다.
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
이것은 신호 마스크를 되돌리는 데 사용됩니다.
kill 함수: 프로세스에 신호를 보냅니다.
(7) 실례: 익명 저장 맵.
익명: 파일 설명자를 통해 경로 이름과 결합하지 않고 후대 프로세스와 공유할 수 있는 저장소를 만듭니다.
(8) 관계없는 두 프로세스 간에 스토리지 세그먼트를 공유하는 방법:
1) XSI 공유 스토리지 함수
2) mmap은 같은 파일을 주소 공간에 매핑합니다.
15.10 POSIX 신호량
(1) POSIX 신호량 인터페이스는 XSI 신호량 인터페이스의 몇 가지 결함을 해결하는 것을 의미한다.
(2) 두 가지 형식:
1) 명명되지 않은 신호량: 메모리에만 존재하며, 신호량을 사용할 수 있는 프로세스가 메모리에 접근해야 합니다.(동일한 프로세스의 스레드 또는 매핑된 메모리)
2) 명명 신호량: 이름을 통해 접근할 수 있으며, 이름이 알려진 프로세스의 모든 라인에서 사용할 수 있다.
(3) POSIX 신호량의 Linux는 파일을 프로세스 주소 공간에 비추고 시스템 호출을 사용하여 각자의 신호량을 조작하지 않았다.
(XSI 신호량보다 뛰어난 성능)
15.12 소결
(1) 권장사항: 파이핑 및 FIFO 사용;메시지 대기열과 신호량의 사용을 피하기 위해 듀플렉스 파이프와 기록 자물쇠를 고려합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.