总览
将代码移植到z / OS平台时面临的主要挑战是z / OS上POSIX信号量API的不可用。 通常,大多数在Linux®/ UNIX™/Windows®平台上运行的程序都是使用POSIX信号量开发的。
解决此问题的一种方法是使用System V API for z / OS实施,而不是POSIX API。 这涉及到遍及整个代码的重大代码更改以及编写代码和测试这种实现的大量工作。 另一个更好的解决方案使用可用的System V API在z / OS中实现POSIX API。 用这种方法,端口的代码更改最少。 这些代码更改从应用程序代码中排除,并作为单独的信号量标头和C文件包含在内。 标头和C文件是通用文件,可以在任何平台上使用。
本文介绍了使用System V Semaphore API实现POSIX Semaphore API的方法。
本文将为需要使用POSIX API但开发平台仅支持System V API(例如z / OS)的开发人员提供巨大帮助。 此外,从开发的角度来看,本文还对POSIX和System V信号量进行了明显区分。
比较POSIX信号量和System V信号量
信号量可以有两种类型:POSIX信号量或System V信号量。
您可以将信号量作为单个单元或集合中的元素进行操作。 由于System V IPC信号量可以成排排列,因此它们的重量非常大。 信号量集由控制结构和单个信号量的数组组成。 一组信号量最多可以包含25个元素。 System V IPC信号量函数是semget()
, semop()
和semctl()
。
-
semget()
-创建一个新的信号量集或通过semget()
系统调用访问现有的信号集。 -
semop()
-执行信号量操作。 -
semctl()
-如果您是信号灯的创建者,请更改其所有权或权限。
POSIX信号量比System V信号量轻得多。 POSIX信号量结构定义单个信号量,而不是信号量数组。 POSIX信号量功能是:
-
sem_open()
-连接到并可选地创建命名信号量 -
sem_init()
-初始化信号量结构(在调用程序内部,因此不是命名信号量) -
sem_close()
-结束与打开信号灯的连接 -
sem_unlink()
-结束与打开的信号灯的连接,并在最后一个进程关闭它时删除该信号灯 -
sem_destroy()
-初始化信号量结构(在调用程序内部,因此不是命名信号量) -
sem_getvalue()
-将信号量的值复制到指定的整数 -
sem_wait()
,sem_trywait()
-在其他进程持有信号量时阻塞,或者如果其他进程持有信号量则返回错误 -
sem_post()
-增加信号量的数量
POSIX带有用于在信号量上创建,初始化和执行操作的简单语义。 它们提供了一种处理进程间通信的有效方法。 如果您需要在一个步骤中实现具有多个增量-减量的原子操作,则System V信号量将非常有用。 除此之外,请坚持使用POSIX信号灯。
z / OS上的信号量限制
z / OS仅支持System V信号量,不支持POSIX信号量。
z / OS上没有POSIX API。 z / OS只有3个用于信号量的System V API,分别是semop()
, semget()
和semctl()
。 如果需要在z / OS中使用信号量API,请单独使用System V API。
表1.各种平台上的信号量支持
的Linux | AIX® | zLinux | 生命值 | 的Solaris | 苹果系统 | z /操作系统 | |
---|---|---|---|---|---|---|---|
POSIX | ÿ | ÿ | ÿ | ÿ | ÿ | ÿ | ñ |
系统V | ÿ | ÿ | ÿ | ÿ | ÿ | ÿ | ÿ |
使用System V信号量API实现POSIX信号量API
所有POSIX信号量函数和类型都在semaphore.h中原型化或定义。 在某些旧版平台(例如z / OS)上,仅System V信号功能可用。 因此,semaphore.h(用于定义POSIX Semaphores函数)在z / OS上不可用。 System V信号量函数在sys / sem.h中原型化
本节说明了使用System V信号量API实现POSIX信号量API的方法。 这是使用POSIX信号在z / OS和AIX中实现并测试得很好的一种方法。
Semaphore_zOS.h和Semaphore_zOS.c这两个单独的文件使用POSIX API在z / OS中实现System V信号灯API。 我们实现的功能是:
int sem_init(int * semid,int pshared,unsigned int值)
使用System V信号量的semget和semctl API来实现此功能(请参见清单1 )。 semget()
函数和semctl()
函数中返回的错误代码与POSIX实现中的相同。
清单1. sem_init函数的实现
int sem_init(int *sem,int pshared,unsigned int value)
{
// get the semaphore first
semid = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666);
if(semid== -1)
/*assign err code and return*/
else
int ret = semctl(*semid,0,SETVAL,value); // initialize the semaphore
if(ret == -1)
/* assign errcode for semctl and return */
return ret;
}
int sem_destroy(int * semid)
清单2显示了如何使用semctl()
函数实现sem_destroy
:
清单2. sem_destroy函数的实现
int ret = semctl(*semid,0,IPC_RMID);
要删除指定的信号量集,请使用IPC_RMID。
int sem_wait(int *中间)
此功能可锁定信号量。 清单3显示了如何使用semop()
实现它。
清单3. sem_wait函数的实现
sb.sem_num=0;
sb.sem_op=-1; //Allocate resources
sb.sem_flg=0;
if (semop(*semid, sb, 1) == -1)
int sem_trywait(int * semid)
此函数还锁定信号量,并使用semop()
。 除了sem_flg = IPC_NOWAIT之外,实现与sem_wait
相似。 参见清单4 。
清单4. sem_trywait函数的实现
sb.sem_num=0;
sb.sem_op=-1; //Allocate resources
sb.sem_flg= IPC_NOWAIT;
if (semop(*semid, sb, 1) == -1)
仅当信号灯当前可用于锁定时,此功能才锁定信号灯。 sem_wait函数将等待,直到信号灯锁定为止,而sem_trywait将不等待。 它只是检查锁当前是否可用,否则它将返回。
int sem_post(int * semid)
此函数使用semop()
释放对信号量的锁定。 参见清单5 。
清单5. sem_post函数的实现
sb.sem_num=0;
sb.sem_op=1; // Release resources.
sb.sem_flg=0;
if (semop(*semid, sb, 1) == -1)
诸如sem_open()
, sem_close()
, sem_unlink()
和sem_getvalue()
类的其他POSIX API尚未实现,因为它不是必需的。 您也可以以相同的方式实现这些!
要为这些实现设置错误代码,请查看其他平台上POSIX实现中的错误代码。
测试应用
在图中的流程图1 , 2 ,和3示出了产生的测试信号的API一个简单的测试应用。 (图1、2和3构成一个流程图,但出于格式化目的而在各节中进行了显示。)测试应用是使用System V信号量实现的。 测试应用程序创建一个线程数组,并使用信号量POSIX API,如sem_init()
, sem_post()
, sem_destroy()
, sem_wait()
, sem_trywait()
等。
图1.测试应用程序的流程图,第1部分
![该图显示了测试应用程序的流程,第1部分](https://i-blog.csdnimg.cn/blog_migrate/59cbff5c8bcfb3425a1990520620d4c4.png)
图2.测试应用程序的流程图,第2部分
![该图显示了测试应用程序的流程,第2部分](https://i-blog.csdnimg.cn/blog_migrate/4de4db0d58f707282a5c8b549a0be055.png)
图3.测试应用程序的流程图,第3部分
![该图显示了测试应用程序的流程,第3部分](https://i-blog.csdnimg.cn/blog_migrate/890902b4e575542df6dacf388cb81e30.png)
案例1-使用POSIX信号量API和使用System V实现的信号量API在AIX上进行测试
本部分显示了测试应用程序的结果,一种使用已经可用的POSIX信号量API,另一种使用在AIX平台上使用System V API实现的POSIX API。 获取信号量的线程顺序因平台和优先级而异。
如果两个测试应用程序的结果完全相等,那么您可以安全地得出结论,使用System V API的POSIX API实现效果很好。
清单6显示了测试应用程序的输出,该应用程序是使用POSIX实现和System V信号量API来实现的:
清单6.使用System V信号量API的测试应用程序输出
bash-3.2# ./test1posiximpln
Thread no 0 id = 258 created
Threadid id =258(ThreadFunction1), locked and incrementing the count
Count (ThreadFunction1) = 1
Thread no 1 id = 515 created
Thread no 2 id = 772 created
Thread no 3 id = 1029 created
Thread id 1029 is in ThreadFunction1, semaphore is already locked and not waiting.
Hence will not increment the counter
Thread no 4 id = 1286 created
Thread no 5 id = 1543 created
Thread no 6 id = 1800 created
Thread id 1800 is in ThreadFunction1, semaphore is already locked and not waiting.
Hence will not increment the counter
Thread no 7 id = 2057 created
Thread no 8 id = 2314 created
Thread no 9 id = 2571 created
Thread id 2571 is in ThreadFunction1, semaphore is already locked and not waiting.
Hence will not increment the counter
Thread 258 going to release lock
Thread id = 515(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 2
Thread id 515 going to release lock
Thread id = 772(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 3
Thread id 772 going to release lock
Thread id = 1286(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 4
Thread id 1286 going to release lock
Thread id = 1543(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 5
Thread id 1543 going to release lock
Thread id = 2057(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 6
Thread id 2057 going to release lock
Thread id = 2314(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 7
Thread id 2314 going to release lock
All threads joined, Final count = 7
bash-3.2#
清单7显示了使用已经存在的POSIX API实现的测试应用程序的输出:
清单7.使用现有的POSIX API测试应用程序输出
bash-3.2# ./test1original
Thread no 0 id = 258 created
Threadid id =258(ThreadFunction1), locked and incrementing the count
Count (ThreadFunction1) = 1
Thread no 1 id = 515 created
Thread no 2 id = 772 created
Thread no 3 id = 1029 created
Thread no 4 id = 1286 created
Thread id 1029 is in ThreadFunction1, semaphore is already locked and not waiting.
Hence will not increment the counter
Thread no 5 id = 1543 created
Thread no 6 id = 1800 created
Thread id 1800 is in ThreadFunction1, semaphore is already locked and not waiting.
Hence will not increment the counter
Thread no 7 id = 2057 created
Thread no 8 id = 2314 created
Thread no 9 id = 2571 created
Thread id 2571 is in ThreadFunction1, semaphore is already locked and not waiting.
Hence will not increment the counter
Thread 258 going to release lock
Thread id = 515(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 2
Thread id 515 going to release lock
Thread id = 772(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 3
Thread id 772 going to release lock
Thread id = 1286(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 4
Thread id 1286 going to release lock
Thread id = 1543(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 5
Thread id 1543 going to release lock
Thread id = 2057(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 6
Thread id 2057 going to release lock
Thread id = 2314(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 7
Thread id 2314 going to release lock
All threads joined, Final count = 7
bash-3.2#
这两个应用程序在AIX中都提供相同的输出。
案例2-使用通过System V实现的信号量API在z / OS上测试应用程序
我们使用z / OS中的相同测试应用程序构建并测试了使用System V信号量实现的信号量文件。 同样在AIX上,我们使用已经可用的POSIX APIS运行了另一个测试应用程序,并比较了输出。
如果测试z / OS的结果与在AIX上的测试结果相同,则可以安全地得出结论,使用System V信号量API的POSIX信号量实现可以正常工作。
清单8显示了z / OS中相同的测试应用程序(与AIX中相同)的输出:
清单8.使用SYTEM V信号量API的测试应用程序输出
STLAB60:../finalCode:> ./test1sys5
Thread no 0 id = 542160384 created
Threadid id =542160384(ThreadFunction1), locked and incrementing the count
Thread no 1 id = 542195200 created Count (ThreadFunction1) = 1
Thread no 2 id = 542199552 created
Thread no 3 id = 542203904 created
Thread no 4 id = 542208256 created
Thread no 5 id = 542212608 created
Thread no 6 id = 542216960 created
Thread no 7 id = 542221312 created
Thread no 8 id = 542225664 created
Thread no 9 id = 542230016 created
Thread id 542216960 is in ThreadFunction1, semaphore is already locked and not waiting.
Hence will not increment the counter
Thread id 542230016 is in ThreadFunction1, semaphore is already locked and not waiting.
Hence will not increment the counter
Thread id 542203904 is in ThreadFunction1, semaphore is already locked and not waiting.
Hence will not increment the counter
Thread 542160384 going to release lock
Thread id = 542195200(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 2
Thread id 542195200 going to release lock
Thread id = 542199552(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 3
Thread id 542199552 going to release lock
Thread id = 542221312(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 4
Thread id 542221312 going to release lock
Thread id = 542225664(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 5
Thread id 542225664 going to release lock
Thread id = 542208256(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 6
Thread id 542208256 going to release lock
Thread id = 542212608(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 7
Thread id 542212608 going to release lock
All threads joined, Final count = 7
清单9显示了使用已经可用的POSIX API在测试应用程序的AIX上的输出:
清单9.使用可用的POSIX API测试应用程序输出
bash-3.2# ./test1original
Thread no 0 id = 258 created
Threadid id =258(ThreadFunction1), locked and incrementing the count
Count (ThreadFunction1) = 1
Thread no 1 id = 515 created
Thread no 2 id = 772 created
Thread no 3 id = 1029 created
Thread no 4 id = 1286 created
Thread id 1029 is in ThreadFunction1, semaphore is already locked and not waiting.
Hence will not increment the counter
Thread no 5 id = 1543 created
Thread no 6 id = 1800 created
Thread id 1800 is in ThreadFunction1, semaphore is already locked and not waiting.
Hence will not increment the counter
Thread no 7 id = 2057 created
Thread no 8 id = 2314 created
Thread no 9 id = 2571 created
Thread id 2571 is in ThreadFunction1, semaphore is already locked and not waiting.
Hence will not increment the counter
Thread 258 going to release lock
Thread id = 515(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 2
Thread id 515 going to release lock
Thread id = 772(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 3
Thread id 772 going to release lock
Thread id = 1286(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 4
Thread id 1286 going to release lock
Thread id = 1543(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 5
Thread id 1543 going to release lock
Thread id = 2057(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 6
Thread id 2057 going to release lock
Thread id = 2314(ThreadFunction2) , locked and incrementing the count
Count (ThreadFunction2) = 7
Thread id 2314 going to release lock
All threads joined, Final count = 7
bash-3.2#
从结果中,您可以看到测试应用程序在z / OS和AIX上显示了相同的行为。
结论
要在任何旧平台(例如z / OS)中使用POSIX信号量API,请下载semaphore.h和semaphore.c文件,然后使用它们来调用任何POSIX API。 我们成功测试了此代码片段,并证明它是正确的。
翻译自: https://www.ibm.com/developerworks/java/library/l-semaphore/index.html