linux信号量_閑の洎茬

来源:百度文库 编辑:神马文学网 时间:2024/04/27 15:18:21
百度空间 | 百度首页  |登录
閑の洎茬
本网页内容大部分用于个人总结
主页博客相册|个人档案 |好友
查看文章
linux信号量
2008-12-08 20:42
1.1 创建信号量
int semget(
key_t key,   //标识信号量的关键字,有三种方法:1、使用IPC——PRIVATE让系统产生,
// 2、挑选一个随机数,3、使用ftok从文件路径名中产生
int nSemes,   //信号量集中元素个数
int flag   //IPC_CREAT;IPC_EXCL 只有在信号量集不存在时创建
)
成功:返回信号量句柄
失败:返回-1
1.2 使用ftok函数根据文件路径名产生一个关键字
key_t ftok(const char *pathname,int proj_id);
路径名称必须有相应权限
1.3 控制信号量
int semctl(
int semid,   //信号量集的句柄
int semnum,   //信号量集的元素数
int cmd,   //命令
/*union senum arg */... //
)
成功:返回相应的值
失败:返回-1
命令详细说明:
cmd: IPC_RMID 删除一个信号量
IPC_EXCL 只有在信号量集不存在时创建
IPC_SET 设置信号量的许可权
SETVAL 设置指定信号量的元素的值为 agc.val
GETVAL 获得一个指定信号量的值
GETPID 获得最后操纵此元素的最后进程ID
GETNCNT 获得等待元素变为1的进程数
GETZCNT 获得等待元素变为0的进程数
union senum 定义如下:
union senum{
int val;
struct semid_ds *buf;
unsigned short * array;
}agc;
其中 semid_ds 定义如下:
struct semid_ds{
struct ipc_pem sem_pem;   //operation pemission struct
time_t sem_otime;   //last semop()time
time_t sem_ctime;   //last time changed by semctl()
struct sem *sembase;   //ptr to first semaphore in array
struct sem_queue *sem_pending; //pending operations
struct sem_queue *sem_pending_last; //last pending operations
struct sem_undo *undo;   //undo requests on this arrary
unsigned short int sem_nsems; //number of semaphores in set
};
1.4 对信号量 +1 或 -1 或测试是否为0
int semop(
int semid,
struct sembuf *sops, //指向元素操作数组
unsigned short nsops //数组中元素操作的个数
)
结构 sembuf 定义
sembuf{
short int sem_num; //semaphore number
short int sem_op; //semaphore operaion
short int sem_flg //operation flag
};
semop
semop系统调用
功能描述:
操作一个或一组信号。 用法:
#include
#include
#include
int semop(int semid, struct sembuf *sops, unsigned nsops);
int  semtimedop(int  semid, struct sembuf *sops, unsigned nsops, struct timespec *timeout); 参数:
semid:信号集的识别码,可通过semget获取。
sops:指向存储信号操作结构的数组指针,信号操作结构的原型如下
struct sembuf
{
unsigned short sem_num;  /* semaphore number */
short          sem_op;   /* semaphore operation */
short          sem_flg;  /* operation flags */
};
这三个字段的意义分别为:
sem_num:操作信号在信号集中的编号,第一个信号的编号是0。
sem_op:如果其值为正数,该值会加到现有的信号内含值中。通常用于释放所控资源的使用权;如果sem_op的值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于sem_op的绝对值。通常用于获取资源的使用权;如果sem_op的值为0,则操作将暂时阻塞,直到信号的值变为0。
sem_flg:信号操作标志,可能的选择有两种
IPC_NOWAIT //对信号的操作不能满足时,semop()不会阻塞,并立即返回,同时设定错误信息。
IPC_UNDO //程序结束时(不论正常或不正常),保证信号值会被重设为semop()调用前的值。这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁,造成该资源永远锁定。
nsops:信号操作结构的数量,恒大于或等于1。
timeout:当semtimedop()调用致使进程进入睡眠时,睡眠时间不能超过本参数指定的值。如果睡眠超时,semtimedop()将失败返回,并设定错误值为EAGAIN。如果本参数的值为NULL,semtimedop()将永远睡眠等待。 返回说明:
成功执行时,两个系统调用都返回0。失败返回-1,errno被设为以下的某个值
E2BIG:一次对信号的操作数超出系统的限制
EACCES:调用进程没有权能执行请求的操作,并且不具有CAP_IPC_OWNER权能
EAGAIN:信号操作暂时不能满足,需要重试
EFAULT:sops或timeout指针指向的空间不可访问
EFBIG:sem_num指定的值无效
EIDRM:信号集已被移除
EINTR:系统调用阻塞时,被信号中断
EINVAL:参数无效
ENOMEM:内存不足
ERANGE:信号所允许的值越界
*********************程序相关信息*********************
程序编号:014
程序编写起始日期:2008.11.2
程序编写完成日期:2008.11.2
程序修改日期:                                   修改备注:
程序目的:学习linux信号量
所用主要函数:ftok(),semget(),semop(),semctl()
程序说明:在本机上运行时,可以把程序中的“./test.c”修改成自己机器上的某个文件(要带路径)
程序完成地点: 宿舍内
*********************程序相关信息*********************/
#include
#include
#include
#include
#include
#include
#include
int main()
{
int pid,val,semid;//中者为可用资源数量,后者为信号灯(即信号量)集的识别代号
key_t semkey;
if((semkey=ftok("./test.c",1))<0)//将文件路径和项目ID(后面那个“1“)转换为System V IPC Key
{
printf("ftok函数转换出现错误。\n");
exit(1);
}
else
printf("ftok函数转换成功,key值为%d\n",semkey);
if((semid=semget(semkey,1,IPC_CREAT|IPC_EXCL|0700))<0)//创建信号灯集,其中包含1个信号灯
{
printf("semget函数创建信号灯集出现错误。\n");
exit(2);
}
else
printf("semget函数创建信号灯集成功,信号灯集识别代号semid为:%d\n",semid);
val=1;
if((semctl(semid,0,SETVAL,val))<0)//此句与上句合起来的功能是将semid对应的信号集中的第一个信号(0表示第一个信号)的可用资源数量设置为1
{
printf("semctl函数设置可用资源数量时出现错误。\n");
exit(9);
}
else
printf("semctl函数设置可用资源数量成功。\n");
if((pid=fork())<0)
{
printf("fork函数创建子进程出现错误。\n");
exit(3);
}
else if(pid>0)//父进程,先索取共享资源,而后释放
{
struct sembuf p_op_buf,v_op_buf;
printf("父进程ID为:%d,该进程将要索取共享资源\n",getpid());
p_op_buf.sem_num=0;
p_op_buf.sem_op=-1;
if(semop(semid,&p_op_buf,1)<0)//以上三行向semid代表的信号灯集的第一个信号灯申请一个资源
{
printf("父进程中,semop函数索取共享资源出现错误。\n");
exit(4);
}
else
{
int i;
printf("父进程中,semop函数索取共享资源成功,索取个数为:%d\n",abs(p_op_buf.sem_op));
printf("ID为%d的父进程现在要睡上6秒钟。\n",getpid());
for(i=6;i>0;i--)
{
printf("%d号进程(父进程)还要睡%d秒钟……\n",getpid(),i);
sleep(1);
}
printf("%d号进程(父进程)已经醒来,并将释放资源。\n",getpid());
v_op_buf.sem_num=0;
v_op_buf.sem_op=1;
p_op_buf.sem_flg=0;//该标志位此处不清零不会出现错误,但下面子进程中的该标志位应清零,因为那时父进程已经占据了资源,子进程申请不到资源的情况下,该标志位如果不清零(比如采用不赋值的默认处理),可能会出现错误。
if(semop(semid,&v_op_buf,1)<0)//以上三行将释放一个资源给semid代表的信号灯集第一个信号灯
{
printf("父进程中,semop函数索取共享资源出现错误。\n");
exit(5);
}
else
{
printf("ID号为%d的父进程中,semop函数释放共享资源成功,释放个数为:%d\n",getpid(),v_op_buf.sem_op);
sleep(1);
}
}
}
else//子进程不断申请共享资源,申请到后声明一下,然后释放
{
struct sembuf p_op_buf,v_op_buf;
sleep(2);//等待父进程将唯一的资源占用
printf("子进程ID为:%d,该进程将要索取共享资源\n",getpid());
p_op_buf.sem_num=0;
p_op_buf.sem_op=-1;
p_op_buf.sem_flg=0;//该标志位不用要清零,此处不清零将出现错误
if(semop(semid,&p_op_buf,1)<0)//向semid代表的信号灯集的第一个信号灯申请一个资源,申请不到就一直在这儿等着,什么时候有了资源,什么时候接着向下进行
{
printf("子进程中,semop函数索取共享资源出现错误:%d\n",errno);
exit(6);
}
else
printf("**********子程序已经成功申请到资源!**********\n");
v_op_buf.sem_num=0;
v_op_buf.sem_op=1;
if(semop(semid,&v_op_buf,1)<0)//以上三行将释放一个资源给semid代表的信号灯集第一个信号灯
{
printf("子进程中,semop函数索取共享资源出现错误。\n");
exit(7);
}
else
{
printf("子进程中,semop函数释放共享资源成功,释放个数为:%d\n",v_op_buf.sem_op);
printf("ID号为%d的进程(子进程)退出!\n",getpid());
if(semctl(semid,0,IPC_RMID,0)<0)
{
printf("调用semctl删除信号量集出现错误。\n");
exit(8);
}
else
{
printf("识别代号为%d的信号量集已经被删除\n",semid);
exit(0);
}
}
}
}
/*********************程序运行结果*********************
[admin@localhost temp]$ ./sem
ftok函数转换成功,key值为16802469
semget函数创建信号灯集成功,信号灯集识别代号semid为:393216
semctl函数设置可用资源数量成功。
父进程ID为:4062,该进程将要索取共享资源
父进程中,semop函数索取共享资源成功,索取个数为:1
ID为4062的父进程现在要睡上6秒钟。
4062号进程(父进程)还要睡6秒钟……
4062号进程(父进程)还要睡5秒钟……
子进程ID为:4063,该进程将要索取共享资源(但此时唯一的资源被父进程所占据,因此一直在此等待资源被释放)
4062号进程(父进程)还要睡4秒钟……
4062号进程(父进程)还要睡3秒钟……
4062号进程(父进程)还要睡2秒钟……
4062号进程(父进程)还要睡1秒钟……
4062号进程(父进程)已经醒来,并将释放资源。
ID号为4062的父进程中,semop函数释放共享资源成功,释放个数为:1
**********子程序已经成功申请到资源!**********(父进程释放资源后,刚才曾经提出申请的子进程就可以申请到资源了)
子进程中,semop函数释放共享资源成功,释放个数为:1
ID号为4063的进程(子进程)退出!
识别代号为393216的信号量集已经被删除
***********************************************************/
类别:lniux学习 |添加到搜藏 |分享到i贴吧 | 浏览(637) |评论 (0)
上一篇:extern void bzero(void *s, int...    下一篇:开始学习Web了
相关文章:
Linux内核的同步机制(原子操作....Linux信号量 共享内存和消息队列
linux 多线程编程---- 信号量的...Linux下通过共享内存进行进程间...
Linux 信号量应用实例(Linux环境...信号量与自旋锁 |Linux,信号量,...
Linux 系统编程笔记 消息队列,...linux 下信号量
linux的常用信号量和进程的四种...Linux中进程间通信:信号量(信号...
更多>>
最近读者:
登录后,您就出现在这里。
hzxing1010恋你在梦里gg297231604gaaranarutoapple7891gaosimengsnowfairy1028linkman_cn
网友评论:
发表评论:
姓 名:   注册 |登录 *姓名最长为50字节
网址或邮箱: (选填)
内 容: 插入表情
▼ 闪光字
验证码: 请点击后输入四位验证码,字母不区分大小写
看不清?

"); //-->
©2009 Baidu