1. 기본 지식
1. 여러 프로세스나 스레드가 동시에 액세스할 수 있는 리소스(변수, 연결 목록, 파일 등)를 공유 리소스라고 하며 중요 리소스라고도 합니다.
2. 이러한 리소스에 액세스하는 코드를 크리티컬 코드라고 하며 이러한 코드 영역을 크리티컬 영역이라고 합니다.
3. P 연산: 프로그램이 크리티컬 섹션에 진입하기 전에 리소스를 신청해야 합니다.
4. V 동작: 프로그램이 크리티컬 섹션을 떠난 후 해당 리소스를 해제해야 합니다.
둘, API
1. semget(세마포어의 ID 가져오기)
2. Semop(세마포어에 대한 P/V 연산 또는 등가 제로 연산)
(1) 세마포어 연산 구조의 정의는 다음과 같다.
1 struct sembuf 2 { 3 unsigned short sem_num; /* 信号量元素序号(数组下标) */ 4 short sem_op; /* 操作参数 PV 操作 */ 5 short sem_flg; /* 操作选项 */ 6 };
(2) 참고: 세마포어 요소의 일련 번호는 0부터 시작하며 실제로는 배열의 첨자입니다.
(3) sem_op의 값에 따라 세마포어 연산은 3가지 경우로 나뉜다.
a.sem_op > 0: 세마포어의 해제를 나타내며, 값의 크기는 해제된 세마포어의 수를 나타낸다.
b. sem_op = 0: 세마포어의 값이 0이 될 때까지 프로그램이 차단됩니다.
c.sem_op < 0: 절대값은 프로그램이 획득하고자 하는 세마포어의 개수를 나타내며
sem_num
이때 지정된 세마포어가 충분하지 않으면 프로그램이 차단된다.
3. semctl(세마포어 관련 속성 가져오기 또는 설정)
3. 단계
4. 코드
1. 데이터 쓰기
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <stdlib.h>
union semun
{
int val; /* 当 cmd 为 SETVAL 时使用 */
struct semid_ds *buf; /* 当cmd为IPC_STAT 或IPC_SET 时使用 */
unsigned short *array; /* 当 cmd 为 GETALL 或 SETALL 时使用 */
struct seminfo *__buf;/* 当 cmd 为 IPC_INFO 时使用 */
};
char * shm_init( void )
{
// 获取key值
int key = ftok("./" , 'X');
// 获取SHM 的ID
int shm_id = shmget(key , 4096 , IPC_CREAT | 0644 );
if (-1 == shm_id )
{
perror("shmget id error");
exit(1); // 直接结束程序(退出进程)
}
// 映射共享内存
char * shm_map = shmat(shm_id , NULL , 0 );
if ((void *) -1 == shm_map)
{
perror("shm map error");
exit(1); // 直接结束程序(退出进程)
}
return shm_map ;
}
int sem_init(void)
{
// 获取一个新的key值
int key = ftok("./" , 'V');
// 获取 信号量的ID
int sem_id = semget(key, 2 , IPC_CREAT | 0644 );
if (-1 == sem_id)
{
perror("sem get id error ");
exit(1);
}
// 初始化信号量的内容 主要是初始化它们的初始的资源数
// 初始化为没有数据 , 有一个空间
union semun set;
set.val = 0 ;
semctl(sem_id , 0, SETVAL , set ); // 初始化数据资源 为 0
set.val = 1 ;
semctl(sem_id , 1, SETVAL , set); // 初始化空间资源 为 1
return sem_id ;
}
int main(int argc, char const *argv[])
{
// 先搞定共享内存并初始化
char * shm_map = shm_init();
// 初始化信号量
int sem_id = sem_init();
// 在写入共享内存之前需要先申请一个空间资源
struct sembuf space ={
.sem_num = 1 , // 需要设置的空间资源的元素下标为 1
.sem_flg = 0 , // 设置标记为 0 啥也不选
.sem_op = -1 // -1 表示资源量即将-1 申请资源
};
struct sembuf data ={
.sem_num = 0 , // 需要设置的空间资源的元素下标为 1
.sem_flg = 0 , // 设置标记为 0 啥也不选
.sem_op = 1 // 1 表示资源量即将加1 释放资源
};
while(1)
{
// 等待空间资源 如果资源暂时不能得到则会阻塞等待(睡眠)
printf("正在等待空间进行写入数据!!!\n");
semop(sem_id , &space , 1 );
printf("已经得到空间, 正在写入数据!!!\n");
printf("请输入需要发送的数据:\n");
fgets(shm_map , 4096 , stdin);
// 设置 数据资源为1
printf("设置数据为 1 \n");
semop(sem_id , &data , 1 );
}
return 0;
}
2. 데이터 읽기
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <stdlib.h>
union semun
{
int val; /* 当 cmd 为 SETVAL 时使用 */
struct semid_ds *buf; /* 当cmd为IPC_STAT 或IPC_SET 时使用 */
unsigned short *array; /* 当 cmd 为 GETALL 或 SETALL 时使用 */
struct seminfo *__buf;/* 当 cmd 为 IPC_INFO 时使用 */
};
char * shm_init( void )
{
// 获取key值
int key = ftok("./" , 'X');
// 获取SHM 的ID
int shm_id = shmget(key , 4096 , IPC_CREAT | 0644 );
if (-1 == shm_id )
{
perror("shmget id error");
exit(1); // 直接结束程序(退出进程)
}
// 映射共享内存
char * shm_map = shmat(shm_id , NULL , 0 );
if ((void *) -1 == shm_map)
{
perror("shm map error");
exit(1); // 直接结束程序(退出进程)
}
return shm_map ;
}
int sem_init(void)
{
// 获取一个新的key值
int key = ftok("./" , 'V');
// 获取 信号量的ID
int sem_id = semget(key, 2 , IPC_CREAT | 0644 );
if (-1 == sem_id)
{
perror("sem get id error ");
exit(1);
}
// 初始化信号量的内容 主要是初始化它们的初始的资源数
// 初始化为没有数据 , 有一个空间
union semun set;
set.val = 0 ;
semctl(sem_id , 0, SETVAL , set ); // 初始化数据资源 为 0
set.val = 1 ;
semctl(sem_id , 1, SETVAL , set); // 初始化空间资源 为 1
return sem_id ;
}
int main(int argc, char const *argv[])
{
// 先搞定共享内存并初始化
char * shm_map = shm_init();
// 初始化信号量
int sem_id = sem_init();
// 在写入共享内存之前需要先申请一个空间资源
// struct sembuf
// {
// unsigned short sem_num; /* 信号量元素序号(数组下标) */
// short sem_op; /* 操作参数 */
// short sem_flg; /* 操作选项 */
// };
struct sembuf space ={
.sem_num = 1 , // 需要设置的空间资源的元素下标为 1
.sem_flg = 0 , // 设置标记为 0 啥也不选
.sem_op = 1 // 1 表示资源量即将加1 申请资源
};
struct sembuf data ={
.sem_num = 0 , // 需要设置的空间资源的元素下标为 1
.sem_flg = 0 , // 设置标记为 0 啥也不选
.sem_op = -1 // -1 表示资源量即将 减1 释放资源
};
while(1)
{
// 等待数据资源 如果资源暂时不能得到则会阻塞等待(睡眠)
printf("正在等待数据的到达!!!\n");
semop(sem_id , &data , 1 );
printf("数据已经到达!!!\n");
printf("Jack 说:%s\n" , shm_map );
// fgets(shm_map , 4096 , stdin);
// 设置 空间资源为1
sleep(2);
printf("数据处理结束 , 设置空间为 1 !!!\n");
semop(sem_id , &space , 1 );
}
return 0;
}