频道栏目
首页 > 资讯 > 其他 > 正文

进程同步与互斥:POSIX有名信号量

15-08-20        来源:[db:作者]  
收藏   我要投稿
在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量。无名信号量一般用于线程间同步或互斥,而有名信号量一般用于进程间同步或互斥。它们的区别和管道及命名管道的区别类似,无名信号量则直接保存在内存中,而有名信号量要求创建一个文件。前面我们学习了无名信号量的使用(详情请看《无名信号量》),这里我们学习有名信号量的使用。


1)创建一个有名信号量
所需头文件:

#include

#include

#include





当有名信号量存在时使用:
sem_t *sem_open(const char *name, int oflag);




当有名信号量不存在时使用:
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
功能:

创建一个有名信号量。

参数:

name:信号量文件名。注意,不能指定路径名。因为有名信号量,默认放在/dev/shm 里,如下图:

flags:sem_open() 函数的行为标志。

mode:文件权限(可读、可写、可执行)的设置。

value:信号量初始值。



返回值:

成功:信号量的地址

失败:SEM_FAILED




2)关闭有名信号量
所需头文件:

#include



int sem_close(sem_t *sem);
功能:

关闭有名信号量。

参数:

sem:指向信号量的指针。

返回值:

成功:0

失败:-1

 



3)删除有名信号量文件
所需头文件:

#include



int sem_unlink(const char *name);
功能:

删除有名信号量的文件。

参数:

name:有名信号量文件名。

返回值:

成功:0

失败:-1

 



4)信号量 PV 操作
用法和《POSIX 无名信号量》一样,详情请点此链接。


有名信号量实现进程间互斥功能:
#include
#include 
#include
#include 
#include
#include 

void printer(sem_t *sem, char *str)
{
sem_wait(sem); //信号量减一
while(*str!='\0')
{
putchar(*str);
fflush(stdout);
str++;
sleep(1);
}
printf("\n");

sem_post(sem); //信号量加一
}


int main(int argc, char *argv[])
{
pid_t pid;
sem_t *sem = NULL;

pid = fork(); //创建进程
if(pid<0){ //出错
perror("fork error");

}else if(pid == 0){ //子进程

//跟open()打开方式很相似,不同进程只要名字一样,那么打开的就是同一个有名信号量
sem = sem_open("name_sem", O_CREAT|O_RDWR, 0666, 1); //信号量值为 1
if(sem == SEM_FAILED){ //有名信号量创建失败
perror("sem_open");
return -1;
}


char *str1 = "hello";
printer(sem, str1); //打印

sem_close(sem); //关闭有名信号量

_exit(1);
}else if(pid > 0){ //父进程


//跟open()打开方式很相似,不同进程只要名字一样,那么打开的就是同一个有名信号量
sem = sem_open("name_sem", O_CREAT|O_RDWR, 0666, 1); //信号量值为 1
if(sem == SEM_FAILED){//有名信号量创建失败
perror("sem_open");
return -1;
}

char *str2 = "world";
printer(sem, str2); //打印


sem_close(sem); //关闭有名信号量


wait(pid, NULL); //等待子进程结束
}

sem_unlink("name_sem");//删除有名信号量

return 0;
}
[cpp] view plaincopy
#include /* For O_* constants */
#include /* For mode constants */ 
#include
#include 

void print(sem_t *print1, sem_t *print2)
{
int i = 0;
while(1)
{
sem_wait(print1);
i++;
printf("int print1 i = %d\n", i);
sem_post(print2);
}
}

int main(int argc, char **argv)
{
sem_t *print1, *print2;

print1 = sem_open("sem_print1", O_CREAT, 0777, 0);
if(SEM_FAILED == print1)
{
perror("sem_open");
}

print2 = sem_open("sem_print2", O_CREAT, 0777, 1);
if(SEM_FAILED == print2)
{
perror("sem_open");
}

print(print1, print2);

return 0;
}
print2.c 代码如下: [cpp] view plaincopy
#include /* For O_* constants */
#include /* For mode constants */ 
#include
#include 

void print(sem_t *print1, sem_t *print2)
{
int i = 0;
while(1)
{
sem_wait(print2);
i++;
printf("in print2 i = %d\n", i);
sleep(1);
sem_post(print1);
}
}


int main(int argc, char **argv)
{
sem_t *print1, *print2;


print1 = sem_open("sem_print1", O_CREAT, 0777, 0);
if(SEM_FAILED == print1)
{
perror("sem_open");
}


print2 = sem_open("sem_print2", O_CREAT, 0777, 1);
if(SEM_FAILED == print2)
{
perror("sem_open");
}


print(print1, print2);


return 0;
}

 
删除有名信号量示例代码如下: [cpp] view plaincopy
#include
#include 

void sem_del(char *name)
{
int ret;

ret = sem_unlink(name);
if(ret < 0)
{
perror("sem_unlink");
}
}


int main(int argc, char **argv)
{
sem_del("sem_print1"); //删除信号量文件sem_print1
sem_del("sem_print2"); //删除信号量文件sem_print2

return 0;
}
makefile 代码如下: [plain] view plaincopy
all:
gcc sem_del.c -o sem_del -lpthread
gcc print1.c -o print1 -lpthread
gcc print2.c -o print2 -lpthread
clean:
rm sem_del print1 print2

 

运行程序时,先把有名信号量删除(sem_del),再分别运行 print1 和 print2:

 

 
相关TAG标签
上一篇:Gozi木马不断拓展攻击范围,东欧国家拉响警报
下一篇:oracle游标:查询并打印员工的姓名和薪水
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站