1. POSIX 标准
POSIX是Portable Operating System Interface of Unix的缩写。由IEEE(Institute of Electrical and Electronic Engineering)开发,由ANSI和ISO标准化。
POSIX的诞生和Unix的发展是密不可分的,Unix于70年代诞生于Bell lab,并于80年代向美各大高校分发V7版的源码以做研究。UC Berkeley在V7的基础上开发了BSD Unix。后来很多商业厂家意识到Unix的价值也纷纷以Bell Lab的System V或BSD为基础来开发自己的Unix,较著名的有Sun OS,AIX,VMS。由于各厂家对Unix的开发各自为政,造成了Unix的版本相当混乱,给软件的可移植性带来很大困难,对Unix的发展极为不利。为结束这种局面,IEEE开发了POSIX,POSIX在源代码级别上定义了一组最小的Unix(类Unix)操作系统接口。
POSIX 表示可移植操作系统接口(Portable Operating System Interface ,缩写为 POSIX 是为了读音更像 UNIX)。电气和电子工程师协会(Institute of Electrical and Electronics Engineers,IEEE)最初开发 POSIX 标准,是为了提高 UNIX 环境下应用程序的可移植性。然而,POSIX 并不局限于 UNIX。许多其它的操作系统,例如 DEC OpenVMS 和 Microsoft Windows NT,都支持 POSIX 标准,尤其是 IEEE Std. 1003.1-1990(1995 年修订)或 POSIX.1,POSIX.1 提供了源代码级别的 C 语言应用编程接口(API)给操作系统的服务程序,例如读写文件。POSIX.1 已经被国际标准化组织(International Standards Organization,ISO)所接受,被命名为 ISO/IEC 9945-1:1990 标准。
POSIX 现在已经发展成为一个非常庞大的标准族,某些部分正处在开发过程中。表 1-1 给出了 POSIX 标准的几个重要组成部分。POSIX 与 IEEE 1003 和 2003 家族的标准是可互换的。除 1003.1 之外,1003 和 2003 家族也包括在表中。
表1:标准的重要组成部分
1003.0
管理 POSIX 开放式系统环境(OSE)。IEEE 在 1995 年通过了这项标准。 ISO 的版本是 ISO/IEC 14252:1996。
1003.1
被广泛接受、用于源代码级别的可移植性标准。1003.1 提供一个操作系统的 C 语言应用编程接口(API)。IEEE 和 ISO 已经在 1990 年通过了这个标准,IEEE 在 1995 年重新修订了该标准。
1003.1b
一个用于实时编程的标准(以前的 P1003.4 或 POSIX.4)。这个标准在 1993 年被 IEEE 通过,被合并进 ISO/IEC 9945-1。
1003.1c
一个用于线程(在一个程序中当前被执行的代码段)的标准。以前是 P1993.4 或 POSIX.4 的一部分,这个标准已经在 1995 年被 IEEE 通过,归入 ISO/IEC 9945-1:1996。
1003.1g
一个关于协议独立接口的标准,该接口可以使一个应用程序通过网络与另一个应用程序通讯。 1996 年,IEEE 通过了这个标准。
1003.2
一个应用于 shell 和 工具软件的标准,它们分别是操作系统所必须提供的命令处理器和工具程序。 1992 年 IEEE 通过了这个标准。ISO 也已经通过了这个标准(ISO/IEC 9945-2:1993)。
1003.2d
改进的 1003.2 标准。
1003.5
一个相当于 1003.1 的 Ada 语言的 API。在 1992 年,IEEE 通过了这个标准。并在 1997 年对其进行了修订。ISO 也通过了该标准。
1003.5b
一个相当于 1003.1b(实时扩展)的 Ada 语言的 API。IEEE 和 ISO 都已经通过了这个标准。ISO 的标准是 ISO/IEC 14519:1999。
1003.5c
一个相当于 1003.1q(协议独立接口)的 Ada 语言的 API。在 1998 年, IEEE 通过了这个标准。ISO 也通过了这个标准。
1003.9
一个相当于 1003.1 的 FORTRAN 语言的 API。在 1992 年,IEEE 通过了这个标准,并于 1997 年对其再次确认。ISO 也已经通过了这个标准。
1003.10
一个应用于超级计算应用环境框架(Application Environment Profile,AEP)的标准。在 1995 年,IEEE 通过了这个标准。
1003.13
一个关于应用环境框架的标准,主要针对使用 POSIX 接口的实时应用程序。在 1998 年,IEEE 通过了这个标准。
1003.22
一个针对 POSIX 的关于安全性框架的指南。
1003.23
一个针对用户组织的指南,主要是为了指导用户开发和使用支持操作需求的开放式系统环境(OSE)框架
2003
针对指定和使用是否符合 POSIX 标准的测试方法,有关其定义、一般需求和指导方针的一个标准。在 1997 年,IEEE 通过了这个标准。
2003.1
这个标准规定了针对 1003.1 的 POSIX 测试方法的提供商要提供的一些条件。在 1992 年,IEEE 通过了这个标准。
2003.2
一个定义了被用来检查与 IEEE 1003.2(shell 和 工具 API)是否符合的测试方法的标准。在 1996 年,IEEE 通过了这个标准。
除了 1003 和 2003 家族以外,还有几个其它的 IEEE 标准,例如 1224 和 1228,它们也提供开发可移植应用程序的 API。要想得到关于 IEEE 标准的最新信息,可以访问 IEEE 标准的主页,网址是 http://standards.ieee.org/。有关 POSIX 标准的概述信息,请访问 Web 站点 http://standards.ieee.org/reading/ieee/stad_public/description/posix/。
2. Liniux下的线程编程
Linux系统下的多线程遵循POSIX线程接口,称为pthread。从上面的描述不难知道,POSIX线程接口是POSIX众多标准中的一个(POSIX 1003.1-2001)。
编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linux下pthread 的实现是通过系统调用 clone() 来实现的。clone() 是Linux所特有的系统调用,它的使用方式类似fork,关于 clone() 的详细情况,有兴趣的读者可以去查看有关文档说明。
下面是一个 POSIX 线程的简单示例程序(thread1.c):
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
void *thread_function(void *arg) ...{
int i;
for ( i=0; i<20; i++) ...{
printf("Thread says hi! ");
sleep(1);
}
return NULL;
}
int main(void) ...{
pthread_t mythread;
if ( pthread_create( &mythread, NULL, thread_function, NULL) ) ...{
printf("error creating thread.");
abort();
}
if ( pthread_join ( mythread, NULL ) ) ...{
printf("error joining thread.");
abort();
}
exit(0);
}
要编译这个程序,只需先将程序存为 thread1.c,然后输入:
$ gcc thread1.c -o thread1 -lpthread
运行则输入:
$ ./thread1
3. Windows下POSIX线程编程
Windows本身没有提供对POSIX的支持。但有一个叫 POSIX Threads for Win32 的开源项目给出了一个功能比较完善的Windows下pthreads API的实现。目前的最新版本是Pthreads-w32 release 2.8.0 (2006-12-22)。
我没有测试过这个最新版本,这里只给出2.7.0版的链接:ftp://sources.redhat.com/pub/pthreads-win32/pthreads-w32-2-7-0-release.exe。
关于该开源项目的详细介绍见:http://sources.redhat.com/pthreads-win32/。
3.1 简单使用
上面的exe文件是一个自解压文件,解压后,Pre-built.2目录中有编译所需要的头文件(include子目录)和库文件(lib子目录)。
一个简单的测试程序(main.cpp):
#include <stdio.h>
#include <pthread.h>
#include <assert.h>
void* Function_t(void* Param)
...{
printf("I am a thread! ");
pthread_t myid = pthread_self();
printf("thread ID=%d ", myid);
return NULL;
}
int main()
...{
pthread_t pid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&pid, &attr, Function_t, NULL);
printf("======================================== ");
getchar();
pthread_attr_destroy(&attr);
return 1;
}
使用 cl.exe 编译(不熟悉 cl.exe 的请参考:http://blog.csdn.net/liuyongjin1984/archive/2008/01/07/2029405.aspx 或者参见下面3.2部分):
3.2 使用VC++ 6.0或Visual Studio 2005来运行上面的程序
关键有两点:
1. 是将头文件(include子目录)和库文件(lib子目录)中的内容添加到VC++ 6.0或Visual Studio 2005开发环境对应的include和lib目录下。
具体来说(以添加include目录为例,添加lib目录类似):
图1:VC++ 6.0(添加include目录:工具--》选项--》目录)
图2:Visual Studio 2005(添加include目录:tools--》options)
2. 指定link时要连接的库的名称(pthreadVC2.lib)
图3:VC++ 6.0(工程--》设置--》连接)
图4:Visual Studio 2005(project-->* property pages)