电子说
// 联合体,用于semctl初始化
union semun
{
int val; /for SETVAL/
struct semid_ds buf;
unsigned short *array;
};
// 初始化信号量
int init_sem(int sem_id, int value)
{
union semun tmp;
tmp.val = value;
if(semctl(sem_id, 0, SETVAL, tmp) == -1)
{
perror("Init Semaphore Error");
return -1;
}
return 0;
}
// P操作:
// 若信号量值为1,获取资源并将信号量值-1
// 若信号量值为0,进程挂起等待
int sem_p(int sem_id)
{
struct sembuf sbuf;
sbuf.sem_num = 0; /序号/
sbuf.sem_op = -1; /P操作/
sbuf.sem_flg = SEM_UNDO;
if(semop(sem_id, &sbuf, 1) == -1)
{
perror("P operation Error");
return -1;
}
return 0;
}
// V操作:
// 释放资源并将信号量值+1
// 如果有进程正在挂起等待,则唤醒它们
int sem_v(int sem_id)
{
struct sembuf sbuf;
sbuf.sem_num = 0; /序号/
sbuf.sem_op = 1; /V操作/
sbuf.sem_flg = SEM_UNDO;
if(semop(sem_id, &sbuf, 1) == -1)
{
perror("V operation Error");
return -1;
}
return 0;
}
// 删除信号量集
int del_sem(int sem_id)
{
union semun tmp;
if(semctl(sem_id, 0, IPC_RMID, tmp) == -1)
{
perror("Delete Semaphore Error");
return -1;
}
return 0;
}
int main()
{
int sem_id; // 信号量集ID
key_t key;
pid_t pid;
// 获取key值
if((key = ftok(".", 'z')) < 0)
{
perror("ftok error");
exit(1);
}
// 创建信号量集,其中只有一个信号量
if((sem_id = semget(key, 1, IPC_CREAT|0666)) == -1)
{
perror("semget error");
exit(1);
}
// 初始化:初值设为0资源被占用
init_sem(sem_id, 0);
if((pid = fork()) == -1)
perror("Fork Error");
else if(pid == 0) /子进程/
{
sleep(2);
printf("Process child: pid=%d\\n", getpid());
sem_v(sem_id); /释放资源/
}
else /父进程/
{
sem_p(sem_id); /等待资源/
printf("Process father: pid=%d\\n", getpid());
sem_v(sem_id); /释放资源/
del_sem(sem_id); /删除信号量集/
}
return 0;
}
上面的例子如果不加信号量,则父进程会先执行完毕。这里加了信号量让父进程等待子进程执行完以后再执行。
共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区。
// 创建或获取一个共享内存:成功返回共享内存ID,失败返回-1
intshmget(key_t key, size_t size, int flag);
// 连接共享内存到当前进程的地址空间:成功返回指向共享内存的指针,失败返回-1
voidshmat(int shm_id, constvoid *addr, int flag);
// 断开与共享内存的连接:成功返回0,失败返回-1
intshmdt(void addr);
// 控制共享内存的相关信息:成功返回0,失败返回-1
intshmctl(int shm_id, int cmd, struct shmid_ds *buf);
当用shmget函数创建一段共享内存时,必须指定其size;而如果引用一个已存在的共享内存,则将size指定为0 。
当一段共享内存被创建以后,它并不能被任何进程访问。必须使用shmat函数连接该共享内存到当前进程的地址空间,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问。
shmdt函数是用来断开shmat建立的连接的。注意,这并不是从系统中删除该共享内存,只是当前进程不能再访问该共享内存而已。
shmctl函数可以对共享内存执行多种操作,根据参数 cmd 执行相应的操作。常用的是IPC_RMID(从系统中删除该共享内存)。
全部0条评论
快来发表一下你的评论吧 !