- 浏览: 162494 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
abc08010051:
简单明了,非常不错
java.lang.Thread.State类详解 -
tenderlitch:
jdk api文档里面的描述...
set闲聊 -
xmind:
图不错,收藏之。
图中Thread.wait()改用Objec ...
java.lang.Thread.State类详解 -
lahvey:
因为你的$VALUE值是“sed.txt”,并不是这个文件的内 ...
条件控制(test,expr……) -
tomotoboy:
thanks
tr用法
有关结构体
1.sem
sem_pid 成员保存了最近一次操作信号量的进程的pid。
sem_semval 成员保存着信号量的计数值。
sem_semncnt 成员保存着等待使用资源的进程数目。
sem_semzcnt 成员保存等待资源完全空闲的的进程数目。
2.semun
semun联合体在senctl()函数中使用,提供 senctl()操作所需要的信息。
3.sembuf
sembuf结构体被semop()函数用来定义对信号量对象的基本操作
sem_num 成员为接受操作的信号量在信号量数组中的序号(数组下标)。
sem_op 成员定义了进行的操作(可以是正、负和零)。
sem_flg 是控制操作行为的标志。
4.semid_qs
和msgqid_ds类似,semid_qs结构被系统用来储存每个信号量对象的有关信息。
其中,
sem_perm 成员保存了信号量对象的存取权限以及其他一些信息。
sem_otime 成员保存了最近一次semop()操作的时间。
sem_ctime 成员保存了信号量对象最近一次改动发生的时间。
sem_base 指针保存着信号量数组的起始地址。
sem_pending 指针保存着还没有进行的操作。
sem_pending_last 指针保存着最后一个还没有进行的操作。
sem_undo 成员保存了 undo请求的数目。
sem_nsems 成员保存了信号量数组的成员数目。
有关的函数
1.semget()
使用semget()函数来建立新的信号量对象或者获取已有对象的标识符。
系统调用: semget()
函数声明: int semget(key_t key,int nsems,int semflg);
返回值: semaphore set IPC identifier on success
2.semop()
使用这个函数来改变信号量对象中各个信号量的状态。
系统调用: semop()
函数声明: int semop(int semid, struct sembuf *sops, unsigned int nsops);
返回值: 0 on success (all operations performed)
第一个参数 semid是要操作的信号量对象的标识符。
第二个参数 sops是sembuf的数组,它定义了semop()函数所要进行的操作序列。
第三个参数 nsops保存着sops数组的长度,也即semop()函数将进行的操作个数。
3.semctl()
和消息队列的msgctl()函数类似,semctl()函数被用来直接对信号量对象进行控制
系统调用: semctl()
函数声明: int semctl(int semid, int semnum, int cmd, union semun arg);
返回值: positive integer on success
比较一下这两个函数的参数我们回发现一些细微的差别。首先,因为信号量对象事实上是多个信息量的集合而非单一的个体,所以在进行操作时,不仅需要指定对象的标识符,还需要用信号量在集合中的序号来指定具体的信号量个体。
两个函数都有cmd参数, 指定了函数进行的具体操作。 不过,和msgctl()函数相比, semctl()函数可以进行的操作要多得多:
IPC_STAT 取得信号量对象的 semid_ds 结构信息,并将其储存在 arg 参数中 buf 指针所指内存中返回。
IPC_SET 用 arg 参数中 buf 的数据来设定信号量对象的的 semid_ds 结构信息。和消息队列对象一样,能被这个函数设定的只有少数几个参数。
IPC_RMID 从内存中删除信号量对象。
GETALL 取得信号量对象中所有信号量的值,并储存在 arg 参数中的 array 数组中返回。
GETNCNT 返回正在等待使用某个信号量所控制的资源的进程数目。
GETPID 返回最近一个对某个信号量调用semop()函数的进程的 pid。
GETVAL 返回对象那某个信号量的数值。
GETZCNT 返回正在等待某个信号量所控制资源被全部使用的进程数目。
SETALL 用 arg 参数中 array数组的值来设定对象内各个信号量的值。
SETVAL 用 arg 参数中val成员的值来设定对象内某个信号量的值。
在消息队列和信号量对象中,都有 IPC_STAT 和 IPC_SET 的操作。但是由于传递参数的类型不同,造成了它们在使用上的差别。在 msgctl()函数中,IPC_STAT 操作只是简单的将内核内 msgqid_ds 结
构的地址赋予buf参数(是一个指针)。而在semctl()函数中, IPC_STAT操作是将 semid_ds 的内容拷贝到 arg 参数的 buf 成员指针所指的内存中。所以,下面的代码会产生错误,而 msgctl()函数的
类似代码却不会:
实例:
1.sem
struct sem { short sempid; /* pid of last operation */ ushort semval; /* current value */ ushort semncnt; /* num procs awaiting increase in semval */ ushort semzcnt; /* num procs awaiting semval = 0 */ };其中,
sem_pid 成员保存了最近一次操作信号量的进程的pid。
sem_semval 成员保存着信号量的计数值。
sem_semncnt 成员保存着等待使用资源的进程数目。
sem_semzcnt 成员保存等待资源完全空闲的的进程数目。
2.semun
semun联合体在senctl()函数中使用,提供 senctl()操作所需要的信息。
union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ ushort *array; /* array for GETALL & SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ void *__pad; };
3.sembuf
sembuf结构体被semop()函数用来定义对信号量对象的基本操作
struct sembuf { unsigned short sem_num; /* semaphore index in array */ short sem_op; /* semaphore operation */ short sem_flg; /* operation flags */ };其中,
sem_num 成员为接受操作的信号量在信号量数组中的序号(数组下标)。
sem_op 成员定义了进行的操作(可以是正、负和零)。
sem_flg 是控制操作行为的标志。
4.semid_qs
和msgqid_ds类似,semid_qs结构被系统用来储存每个信号量对象的有关信息。
struct semid_ds { struct ipc_perm sem_perm; /* permissions .. see ipc.h */ __kernel_time_t sem_otime; /* last semop time */ __kernel_time_t sem_ctime; /* last change time */ struct sem *sem_base; /* ptr to first semaphore in array */ struct sem_queue *sem_pending; /* pending operations to be processed */ struct sem_queue **sem_pending_last; /* last pending operation */ struct sem_undo *undo; /* undo requests on this array */ unsigned short sem_nsems; /* no. of semaphores in array */ };
其中,
sem_perm 成员保存了信号量对象的存取权限以及其他一些信息。
sem_otime 成员保存了最近一次semop()操作的时间。
sem_ctime 成员保存了信号量对象最近一次改动发生的时间。
sem_base 指针保存着信号量数组的起始地址。
sem_pending 指针保存着还没有进行的操作。
sem_pending_last 指针保存着最后一个还没有进行的操作。
sem_undo 成员保存了 undo请求的数目。
sem_nsems 成员保存了信号量数组的成员数目。
有关的函数
1.semget()
使用semget()函数来建立新的信号量对象或者获取已有对象的标识符。
系统调用: semget()
函数声明: int semget(key_t key,int nsems,int semflg);
返回值: semaphore set IPC identifier on success
int open_semaphore_set(key_t keyval, int numsems) { int sid; if(!numsems) return(-1); if((sid=semget(keyval,numsems,IPC_CREAT|0660))==-1) { return(-1); } return(sid); }函数的第二个参数 nsems 是信号量对象所特有的,它指定了新生成的信号量对象中信号量的数目,也就是信号量数组成员的个数。
2.semop()
使用这个函数来改变信号量对象中各个信号量的状态。
系统调用: semop()
函数声明: int semop(int semid, struct sembuf *sops, unsigned int nsops);
返回值: 0 on success (all operations performed)
第一个参数 semid是要操作的信号量对象的标识符。
第二个参数 sops是sembuf的数组,它定义了semop()函数所要进行的操作序列。
第三个参数 nsops保存着sops数组的长度,也即semop()函数将进行的操作个数。
3.semctl()
和消息队列的msgctl()函数类似,semctl()函数被用来直接对信号量对象进行控制
系统调用: semctl()
函数声明: int semctl(int semid, int semnum, int cmd, union semun arg);
返回值: positive integer on success
比较一下这两个函数的参数我们回发现一些细微的差别。首先,因为信号量对象事实上是多个信息量的集合而非单一的个体,所以在进行操作时,不仅需要指定对象的标识符,还需要用信号量在集合中的序号来指定具体的信号量个体。
两个函数都有cmd参数, 指定了函数进行的具体操作。 不过,和msgctl()函数相比, semctl()函数可以进行的操作要多得多:
IPC_STAT 取得信号量对象的 semid_ds 结构信息,并将其储存在 arg 参数中 buf 指针所指内存中返回。
IPC_SET 用 arg 参数中 buf 的数据来设定信号量对象的的 semid_ds 结构信息。和消息队列对象一样,能被这个函数设定的只有少数几个参数。
IPC_RMID 从内存中删除信号量对象。
GETALL 取得信号量对象中所有信号量的值,并储存在 arg 参数中的 array 数组中返回。
GETNCNT 返回正在等待使用某个信号量所控制的资源的进程数目。
GETPID 返回最近一个对某个信号量调用semop()函数的进程的 pid。
GETVAL 返回对象那某个信号量的数值。
GETZCNT 返回正在等待某个信号量所控制资源被全部使用的进程数目。
SETALL 用 arg 参数中 array数组的值来设定对象内各个信号量的值。
SETVAL 用 arg 参数中val成员的值来设定对象内某个信号量的值。
int get_sem_val(int sid, int semnum) { return(semctl(sid,semnum,GETVAL,0)); }上面的代码返回信号量对象中某个信号量的值。注意这里 semctl()函数的最后一个参数取的是零,这是因为执行 GETVAL 命令时这个参数被自动忽略了。
void init_semaphore(int sid, int semnum, int initval) { union semun semopts; semopts.val=initval; semctl(sid, semnum, SETVAL, semopts); }上面的代码用 initval参数来设定信号量对象中某个信号量的值。
在消息队列和信号量对象中,都有 IPC_STAT 和 IPC_SET 的操作。但是由于传递参数的类型不同,造成了它们在使用上的差别。在 msgctl()函数中,IPC_STAT 操作只是简单的将内核内 msgqid_ds 结
构的地址赋予buf参数(是一个指针)。而在semctl()函数中, IPC_STAT操作是将 semid_ds 的内容拷贝到 arg 参数的 buf 成员指针所指的内存中。所以,下面的代码会产生错误,而 msgctl()函数的
类似代码却不会:
void getmode(int sid) { int rc; union semun semopts; /*下面的语句会产生错误*/ if((rc=semctl(sid, 0, IPC_STAT, semopts))==-1) { perror("semctl"); } printf("Pemission Mode were %o\n", semopts.buf->sem_perm.mode); return; }为什么呢?因为实现没有给 buf 指针分配内存,其指向是不确定的。这种“不定向”的指针是 C 程序中最危险的陷阱之一。改正这个错误,只需要提前给 buf 指针准备一块内存。下面是修改过的代码:
void getmode(int sid) { int rc; union semun semopts; struct semid_ds mysemds; /*给buf指针准备一块内存*/ semopts.buf=&mysemds; /*现在OK了*/ if((rc=semctl(sid, 0, IPC_STAT, semopts))==-1) { perror("semctl"); } printf("Pemission Mode were %o\n", semopts.buf->sem_perm.mode); return; }
实例:
semtool.c #include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #define SEM_RESOURCE_MAX 1 /*Initial value of all semaphores*/ void opensem(int *sid, key_t key); void createsem(int *sid, key_t key, int members); void locksem(int sid, int member); void unlocksem(int sid, int member); void removesem(int sid); unsigned short get_member_count(int sid); int getval(int sid, int member); void dispval(int sid,int member); void changemode(int sid, char *mode); void usage(void); int main(int argc, char *argv[]) { key_t key; int semset_id; if(argc == 1) usage(); /*Create unique key via call to ftok()*/ key=ftok(".",'s'); switch(tolower(argv[1][0])) { case 'c': if(argc!=3)usage(); createsem(&semset_id, key, atoi(argv[2])); break; case 'l': if(argc!=3) usage(); opensem(&semset_id, key); locksem(semset_id, atoi(argv[2])); break; case 'u': if(argc!=3) usage(); opensem(&semset_id, key); unlocksem(semset_id, atoi(argv[2])); break; case 'd': opensem(&semset_id,key); removesem(semset_id); break; case 'm': opensem(&semset_id, key); changemode(semset_id, argv[2]); break; default: usage(); } return(0); } void opensem(int *sid, key_t key) { /*Open the semaphore set ---do not creat!*/ if((*sid=semget(key, 0 , 0666)==-1) { printf("Semaphore set does not exist!\n"); exit(1); } } void createsem(int *sid, key_t key, int members) { int cntr; union semun semopts; if(members > SEMMSL){ printf("Sorry,max number of semaphores in a set is %d\n",SEMMSL); exit(1); } printf("Attempting to create new semaphore set with %d members\n",members); if((*sid=semget(key, members, IPC_CREAT|IPC_EXCL|0666))==-1) { fprintf(stderr,"Semaphore set already exist!\n"); exit(1); } semopts.val= SEM_RESOURCE_MAX; /*Initialize all members(could be done with SETALL)*/ for(cntr=0;cntr<members;cntr++) { semctl(*sid, cntr, SETVAL, semopts); } } void locksem(int sid, int member) { struct sembuf sem_lock={0, -1, IPC_NOWAIT}; if(member <0 ||member>(get_member_count(sid) -1)) { fprintf(stderr,"semaphore member %d out of range\n", member); return; } /*Attempt to lock the semphore set*/ if(!getval(sid, member)) { fprintf(stderr,"Semaphore resources exhausted (no lock)\n") exit(1); } sem_lock.sem_num =member; if((semop(sid, &sem_lock, 1)==-1) { fprintf, "Lock faild\n"); exit(1); } else printf("Semaphore resources decremented by one (locked)\n"); dispval(sid ,member); } void unlocksem(int sid, int member) { struct sembuf sem_unlock={member, 1, IPC_NOWAIT}; int semval; if(member<0 || member>(get_member_count(sid)-1)) { fprintf(stderr,"Semaphore member %d out of range\n",member); return; } /*Is the semaphore set locked? */ semval =getval(sid, member); if(semval==SEM_REOURSE_MAX){ fprintf(stderr, "Semaphore not locked!\n"); exit(1); } sem_unlock.sem_num = member; /*Attempt to lock the semaphore set*/ if((semop(sid, &sem_unlock, 1))==-1) { fprintf(stderr, "Unlock failed\n"); exit } else printf("Semaphore resources incremented by one(unlocked)\n"); dispval(sid, member); } void removesem(int sid) { semctl(sid, 0, IPC_RMID,0); print("Semaphore removed\n"); } unsigned short get_member_count(int sid) { union semum semopts; struct semid_ds mysemds; semopts.buf= &mysemds; /*Return number of member in the semaphore set*/ int rc; if((rc=semctl(sid, 0, IPC_STAT, semopts))==-1) { perror("semctl"); return(-1) } return(semopts.buf->sem_nsems); } int getval(int sid, int member) { int semval; semval= semctl(sid, member,GETVAL, 0) reval semval; } void changemode(int sid, char *mode) { int rc; union semun semopts; struct semid_ds mysemds; /*Get current values for internal data structure */ semopts.buf=&mysemds; rc = semctl(sid, 0, IPC_STAT, semopts); if(rc ==-1) { perror("semctl"); exit(1); } printf("Old permission were %o\n", semopts.buf->perm.mode); /* Change the permission on the semaphore */ sscanf(mode,"%ho",&semopts.buf->sem_perm.mode); /*Update the internal data structure */ semctl(sid,0, IPC_SET, semopts); printf("Updated......\n"); } void dispval(int sid, int member) { int semval; semval= semctl(sid, member, GETVAL,0); printf("semval for member %d is %d\n", member ,semval); } void usage(void) { fprintf(stderr, "semtool -Autility for thinking with semaphores\n"); fprintf(stderr, "\nUSAGE: semtool (c)reate <semcount>\n"); fprintf(stderr, " (l)ock <sem #>\n"); fprintf(stderr, " (u)nlock <sem #>\n"); fprintf(stderr, " (d)elete\n"); fprintf(stderr, " (m)ode <mode>\n"); exit(1); }
发表评论
-
Berkeley套接字的一些基本知识
2009-10-25 00:46 4198一、首先看一下Berkeley S ... -
进程间通信——共享内存
2009-10-18 15:02 4891共享内存(Shared Memory) 共享内存,简单的说就是 ... -
进程间通信——消息队列
2009-10-08 21:41 5832原文地址:http://hi.baidu. ... -
linux/unix锁
2009-10-07 19:54 2568锁定中的几个概念 ... -
文件共享
2009-08-14 14:58 1602UNIX支持在不同进程间共 ... -
文件I/O
2009-08-13 02:06 1166本文将对UNIX系统的文件 ... -
进程间通信——管道
2009-08-13 00:02 17161.匿名管道 匿名管道创建的四种方法 使用pipe()函数 ... -
进程间通信——系统调用setjmp()与longjmp()
2009-08-10 23:05 2558系统调用setjmp()和 longjmp() 有时候,当接收 ... -
进程间通信——信号
2009-08-10 13:21 3435信号类型 信号类型在Trap命令详解中有详细的介绍 信号捕捉 ... -
进程控制——进程环境
2009-08-09 14:49 1163进程环境 进程的环境是一个以 NULL 字符结尾的字符串之集合 ... -
gcc编译器入门
2009-08-07 18:51 1143Gcc编译流程: 预处理(Pre-Processing); ... -
Makefile文件的制作
2009-08-07 15:29 1623当我们有很多C源文件的时候,我们每次运行都要对其编译、链接…… ... -
unix下第一个C程序
2009-08-07 14:53 987首先我们的目录下有两个C程序,功能很简单就是求一个整数的阶乘 ... -
UNIX 进程揭秘——探索运行在 UNIX 操作系统下的进程的生命周期
2009-08-03 10:40 1008原文地址:http://www.ibm.com/develop ... -
unix进程(初识)
2009-07-28 17:24 1265原文地址:http://blog.chinaunix.net/ ... -
linux进程
2009-07-28 16:49 1114原文地址:http://it.china- ...
相关推荐
关于信号量的文章,生产者消费者问题与读者写者问题---信号量机制,PV操作——进程同步的信号量问题,利用信号机制实现的 父子进程同步,嵌入式linux的学习笔记-进程间通信的信号与信号集(四)1)进程的同步与互斥 ...
之前用过Prosix版本的共享内存和信号量,一直没有实践System V版本的,主要是因为其信号量集的概念操作有些复杂,今天试着写一个SV版本的共享内存进程间通信,使用信号量同步。程序提供了几个简单的用于操作SV版本...
主要介绍了详解Linux进程间通信——使用信号量,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
进程间通信之套接字( socket ) 网络间通信 七种进程间通信方式: 一.无名管道( pipe ) 二.有名管道( fifo ) 三.共享内存 ( shared memory ) 四.信号 ( sinal ) 五.消息队列 ( message queue ) 六.信号量 ( ...
进程间通信之消息队列 ( message queue ) 消息队列是消息的链表,具有特定的格式,并由消息队列标识符标识. 七种进程间通信方式: 一.无名管道( pipe ) 二.有名管道( fifo ) 三.共享内存 ( shared memory ) 四....
Linux 下进程间通信实例之一——共享内存 使用了信号量用于进程间的同步
进程在核心的协调下进行相互间的通讯机制——管道,信号量,消息队列。
进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问...
良好的进程间通信(IPC)机制是提高UNIX程序性能的关键。本书全面深入地讲解了各种进程间通信形式,包括消息传递、同步、共享内存及远程调用(RPC)。书中包含了大量经过优化的源代码,帮助读者加深理解。这些源代码...
实例268——使用信号量(Semaphore)实现线程的同步 实例269——使用多线程进行文件搜索 实例270——获取当前系统的所有进程 实例271——实现应用程序在系统中只能运行一个实例 实例272——获取所有打开窗口...
在操作系统中,有些进程存在着相互制约的关系,这些制约关系来源于并行... 这种机制就叫做进程间通信,或IPC.在linux 中支持UNIX SYSTEM V 的三种通信机制: 消息队列, 信号量和共享内存. 现就消息队列这种机制进行分析.
4.4.3 使用信号量(Semaphore) 84 4.4.4 使用事件(Event) 84 4.4.5 各种方法的比较 85 4.5 多线程串口程序设计 85 4.5.1 多线程的应用框架 85 4.5.2 相关的声明 86 4.5.3 创建线程 87 4.5.4 编写线程函数 87 ...
第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6.5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 第7章基于socket的进程间通信 7.1系统调用...
第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6.5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 第7章基于socket的进程间通信 7.1系统调用...
(3)各相关进程间通过什么信号量实现彼此的制约,标明信号量的含义和初值; (4)用P、V操作写出相应的代码段; (5)验证代码的正确性:设以不同的次序运行各进程,是否能保证问题的圆满解决。切忌按固定顺序执行...
第7章 基于socket的进程间通信 7.1 系统调用socket() 7.2 函数sys—socket()——创建插口 7.3 函数sys—bind()——指定插口地址 7.4 函数sys—listen()——设定server插口 7.5 函数sys—accept()——接受...
接着系统地讲解了嵌入式Linux的环境搭建,以及嵌入式Linux的I/O与文件系统的开发、进程控制开发、进程间通信开发、网络应用开发、基于中断的开发、设备驱动程序的开发以及嵌入式图形界面的开发等,并且还安排了丰富...
第6章 传统的Unix进程间通信 6.1 概述 6.2 管道和系统调用pipe() 6.3 命名管道 6.4 信号 6. 5 系统调用ptrace()和进程跟踪 6.6 报文传递 6.7 共享内存 6.8 信号量 《LINUX内核源代码情景分析(下册)》图书...
第 7章 基于socket的进程间通信 7.1 系统调用socket() 7.2 函数sys—socket()——创建插口 7.3 函数sys—bind()——指定插口地址 7.4 函数sys—listen()——设定server插口 7.5 函数sys—accept()——接受连接...