关闭

关闭

封号提示

内容

首页 系统调用相关函数.doc

系统调用相关函数.doc

系统调用相关函数.doc

上传者: 黄威 2011-06-25 评分 4.5 0 54 7 246 暂无简介 简介 举报

简介:本文档为《系统调用相关函数doc》,可适用于IT/计算机领域,主题内容包含窗体顶端索引:fork、exec和exit对IPC对象的影响fcntl记录锁管道和FIFO的属性管道和FIFO的限制pipe函数popen和pclo符等。

窗体顶端索引:fork、exec和exit对IPC对象的影响fcntl记录锁管道和FIFO的属性管道和FIFO的限制pipe函数popen和pclosemkfifo函数SystemVIPC共性描述msqidds结构msgget函数msgsnd函数msgrcv函数msgctl函数在SystemV消息队列上使用select和pollsemidds结构semget函数semop函数semctl函数shmidds结构shmget函数shmat函数shmdt函数shmctl函数mmap函数munmap函数msync函数匿名内存映射 fork、exec和exit对IPC对象的影响IPC类型forkexecexit    管道和FIFO子进程取得父进程的所有打开着的描述字的拷贝所有打开的描述字继续打开着除非已设置描述字的FDCLOEXEC位关闭所有打开着的描述字最后一个关闭时删除管道或FIFO中残留的所有数据Posix消息队列子进程取得父进程的所有打开着的消息队列描述字的拷贝关闭所有打开着的消息队列描述字关闭所有打开着的消息队列描述字SystemV消息队列没有效果没有效果没有效果Posix互斥锁、条件变量、读写锁、基于内存的信号灯若驻留在共享内存中而且具有进程间共享属性则共享除非在继续打开着的共享内存中而且具有进程间共享属性否则消失除非在继续打开着的共享内存中而且具有进程间共享属性否则消失Posix有名信号灯父进程中所有打开着的有名信号灯在子进程中继续打开着关闭所有打开着的有名信号灯关闭所有打开着的有名信号灯SystemV信号灯子进程中所有semadj值都置为所有semadj值都携入新程序中所有semadj值都加到相应的信号灯上fcntl记录上锁子进程不继承父进程持有的锁只要描述字继续打开着锁就不变解开由进程持有的所有未处理的锁mmap内存映射和Posix共享内存区父进程中的内存映射存留到子进程中去除内存映射去除内存映射SystemV共享内存区附接着的共享内存区在子进程中继续附接着断开所有附接着的共享内存区断开所有附接着的共享内存区门子进程取得父进程的所有打开着的描述字但是客户在门描述字上激活其过程时只有父进程是服务器所有门描述字都应关闭因为它们创建时设置了FDCLOEXEC位关闭所有打开着的描述字 fcntl记录锁Unix内核没有文件内记录的概念这里的记录是指字节范围(byterange)。Posix记录上锁定义了一个特殊的字节范围以指定整个文件它的其始偏移为(文件的开头)长度为。文件上锁是记录上锁的一个特例。粒度(granularity)用于标记能被锁住的对象的大小。对于Posix记录上锁来说粒度就是单个字节。记录上锁的Posix接口是fcntl函数:#include<fcntlh>intfcntl(intfd,intcmd,…*structflock*arg*)返回:成功时取决于cmd出错时为。对应记录上锁的第三个参数arg是指向某个flock结构的指针:structflock{    shortltype*FRDLCK,FWRLCK,FUNLCK*    shortlwhence*SEEKSET,SEEKCUR,SEEKEND*    offtlstart*relativestartingoffsetinbytes*    offtllen*#bytesmeansuntilendoffile*    pidtpid*PIDreturnedbyFGETLK*}cmd命令有三个:        FSETLK:获取(ltype为FRDLCK或FWRLCK)或释放(ltype为FUNLCK)由arg指向的flock结构所描述的锁。如果该锁无法授予调用进程该函数就立即返回一个EACCES或EAGAIN错误而不阻塞。        FSETLKW:该命令与上一命令相似不同在于若所请求的锁无法授予则调用进程将阻塞到该锁能够授予为止。(W的意思是“等待”)        FGETLK:检查由arg指向的锁以确定是否有某个已存在的锁会妨碍新锁授予调用进程。如果当前没有这样的锁存在由arg指向的flock结构的ltype被置为FUNLCK。否则关于这个已存在锁的信息将在由arg指向的flock结构中返回(该结构的内容由fcntl函数覆写)其中包含持有该锁的进程ID。lwhence成员有三个值:        SEEKSET:lstart相对于文件的开头解释        SEEKCUR:lstart相对与文件的当前字节偏移解释        SEEKEND:lstart相对于文件的末尾解释。llen成员指定从该偏移开始的连续字节数。长度为表示锁住整个文件一般锁整个文件如下使用:指定lwhence成员为SEEKSETlstart为llen为。fcntl记录上锁既可用于读也可用于写对于一个文件的任意字节最多只能存在一种类型的锁(读出锁或写入锁)。而且一个给定字节可以有多个读出锁但只能有一个写入锁。当一个描述字不是打开来用于读时如果我们对它请求一个读出锁错误就会发生同样当一个描述字不是打开来用于写时请求一个写锁错误也会发生。对于一个打开着某个文件的给定进程来说当它关闭该文件的任何一个描述字或终止时与该文件关联的所有锁都被删除。锁不能通过fork由子进程继承。删除锁的关键是进程ID而不是引用同一文件的描述字数目及打开目的。记录上锁不应该同标准IO函数库一块使用因为该函数库会执行内部缓冲。当某个文件需要上锁时为避免问题应对它使用read和write。使用fcntl上锁和解锁的例子见unpve:locklockfcntlc。 劝告性锁和强制性锁Posix记录上锁是劝告性锁(advisorylocking)。劝告性锁对协作进程(cooperatingprocesses)是足够了。有些系统提供了强制性锁(mandatorylocking)。使用强制性锁后内核将检查每个read和write请求以验证其操作不会干扰由某个进程持有的某个锁。对于通常的阻塞式描述字与某个强制性锁冲突的read或write将把调用进程投入睡眠直到该锁释放为止。对于非阻塞式描述字与某个强制性锁冲突的read或write将导致它们返回一个EAGAIN错误。对某个特定文件施行强制性锁应满足:        组成员执行位必须关闭        SGID位必须打开。强制性锁不需要新的系统调用。虽然强制性上锁有一定作用但多个进程在更新同一个文件时仍然会导致混乱。进程之间还是需要某种上锁形式的协作。当一个文件区被锁住时待处理的读出者和写入者的优先级是不可知的。管道和FIFO的属性非阻塞方式对管道和FIFO的影响(设置方式:open时指定ONONBLOCK或使用fcntl使能ONONBLOCK标志):当前操作管道或FIFO的现有打开操作阻塞(缺省)时返回ONONBLOCK时返回openFIFO只读FIFO打开来写成功返回成功返回FIFO不是打开来写阻塞到FIFO打开来写为止成功返回openFIFO只写FIFO打开来读成功返回成功返回FIFO不是打开来读阻塞到FIFO打开来读为止返回ENXIO错误从空管道或空FIFOread管道或FIFO打开来写阻塞到管道或FIFO中有数据或管道或FIFO不再为写打开为止返回EAGAIN错误管道或FIFO不是打开来写read返回(文件结束符)read返回(文件结束符)往管道或FIFOwrite管道或FIFO打开来读(见如下说明)(见如下说明)管道或FIFO不是打开来读给线程产生SIGPIPE给线程产生SIGPIPE其他规则:如果请求读出的数据量多于管道或FIFO中当前可用数据量那么只返回这些可用的数据。如果请求写入的数据的字节数小于或等于PIPEBUF(一个Posix限制值)那么write操作保证是原子的。ONONBLOCK标志的设置对于write操作的原子性没有影响。然而当一个管道或FIFO设置成非阻塞时来自write的返回值取决于待写的字节数以及该管道或FIFO中当前可用空间的大小。如果待写的字节数小于等于PIPEBUF:()如果该管道或FIFO中有足以存放所请求字节数的空间那么所有数据字节都写入()如果该管道或FIFO中没有足以存放所请求字节数的空间那么立即返回一个EAGAIN错误。如果待写的字节数大于PIPEBUF:()如果该管道或FIFO中至少有字节空间那么内核写入该管道或FIFO能容纳数目的数据字节该数目同时作为来自write的返回值()如果该管道或FIFO已满那么立即返回一个EAGAIN错误。如果写入一个没有打开着用于读的管道或FIFO那么内核将产生一个SIGPIPE信号。该信号的缺省动作是终止进程。如果调用进程忽略了该信号或捕获了该信号并从其信号处理程序中返回那么write返回一个EPIPE错误。处理SIGPIPE信号的最容易方法是忽略它让write返回EPIPE错误应用应该检查write的返回值。注意:使用管道的程序一定要为SIGPIPE信号做好准备。管道和FIFO的限制系统加于管道和FIFO的唯一限制是:        OPENMAX:一个进程在任意时刻打开的最大描述字数。        PIPEBUF:可原子的写往一个管道或FIFO的最大数据量。OPENMAX的值可通过sysconf函数查询。PIPEBUF的值通常定义在<limitsh>中但也可在运行时通过调用pathconf或fpathconf取得。尽管针对管道的PIPEBUF能够修改但具体依赖于路径名所存放的底层文件系统实际应该很少这么做。pipe函数#include<unistdh>intpipe(intfd)返回:成功时为出错时为。创建一个管道函数返回两个描述字:fd和fd前者打开来读后者打开来写。宏SISFIFO可用于确定一个描述字或文件是否或是管道或是FIFO。它的唯一参数是stat结构的stmode成员计算结果或为真(非零)或者为假()。管道是通过内核运作的使用管道传输的每个字节的数据都穿越了用户内核接口两次:一次是在写入管道时一次是在从管道读出时。注意:对管道的read只要该管道中存在一些数据就会马上返回它不必等待达到所请求的字节数。popen和pclose#include<stdioh>FILE*popen(constchar*command,constchar*type)返回:成功时为文件指针出错时为。intpclose(FILE*stream)返回:成功时为shell的终止状态出错时为。popen函数创建一个管道并启动另一个进程该进程或者从该管道读出标准输入或者往该管道写入标准输出。其中command是一个shell命令行它由sh程序处理。popen在调用进程和所指定的命令之间创建一个管道由popen返回的值是一个标准IOFILE指针该指针或者用于输入或者用于输出具体取决于字符串type:        如果type为r那么调用进程读进command的标准输出。        如果type为w那么调用进程写到command的标准输入。pclose函数关闭由popen创建的标准IO流stream等待其中的命令终止然后返回shell的终止状态。mkfifo函数#include<systypesh>>#include<sysstath>intmkfifo(constchar*pathname,modetmode)返回:成功是为出错时为。FIFO类似于管道它是一个单向(半双工)数据流每个FIFO有一个路径名与之关联从而允许无亲缘关系的进程访问同一个FIFO也称为有名管道(namedpipe)。FIFO由mkfifo创建。其中pahtname是一个普通的UNIX路径名它是该FIFO的名字mode参数指定文件权限位类似于open的第三个参数。mkfifo已经隐含指定OCREAT|OEXCL即要么创建一个新的FIFO要么返回一个EEXIST错误。一个FIFO创建完毕后它必须或者打开来读或者打开来写它不能打开来既读又写因为它是半双工的。对管道或FIFO的write总是往末尾添加数据对它们的read总是从开头返回数据。如果对管道或FIFO调用lseek将返回ESPIPE错误。打开FIFO进行处理有时序上的问题。如果当前没有任何进程打开某个FIFO来写那么打开该FIFO来读的进程将阻塞。所以在多进程操作FIFO时要防止死琐的产生。SystemVIPC共性描述SystemVIPC指以下三种类型的IPC:        SystemV消息队列        SystemV信号灯        SystemV共享内存区所有SystemVIPC函数列表: 消息队列信号灯共享内存区头文件sysmsghsyssemhsysshmh创建或打开函数msggetsemgetshmget控制操作函数msgctlsemctlshmctl操作函数msgsndmsgrcvsemopshmatshmdt  keyt键和ftok函数SystemVIPC使用keyt值作为它们的名字。头文件<systypesh>把keyt定义为一个整数它通常是一个至少位的整数。这些整数通常是由ftok函数赋予的。ftok函数把一个已存在的路径名和一个整数标识符转换成一个keyt值称为IPC键(IPCkey):#include<sysipch>keytftok(constchar*pahtname,intid)返回:成功时为IPC键出错时为。如果pathname不存在或者对调用进程不可访问ftok返回。注意:        不能保证两个不同的路径名与同一个id值的组合产生不同的键。        用于产生键的pahtname不能是服务器存活期间由它反复创建并删除的文件否则会导致ftok多次调用返回不同的值。  ipcperm结构内核为每个IPC对象维护一个信息结构:structipcperm{    uidtuid*owner'suserid*    gidtgid*owner'sgroupid*    uidtcuid*creator'suserid*    gidtcgid*creator'sgroupid*    modetmode*accessmodes*    ulongtseq*slotusagesequencenumber*    keytkey*key*}  创建与打开IPC对象创建或打开一个IPC对象需要一个类型为keyt的IPC键对此键应用有两种选择:   调用ftok给它传递pathname和id   指定IPCPRIVATE它保证创建一个新的、唯一的IPC对象。创建或打开一个IPC对象函数共同的另一个参数是oflag它指定IPC对象的读写权限位(ipcperm结构中的mode成员)并选择是创建一个新的IPC对象还是访问一个存在的IPC对象。选择的规则如下:oflag标志不存在已存在无特殊标志出错errno=ENOENT成功引用已存在对象IPCCREAT成功创建新对象成功引用已存在对象IPCCREAT|IPCEXCL成功创建新对象出错errno=EEXIST注意:设置IPCEXCL但不设置IPCCREAT没有意义。权限位的设置如下(八进制):        :由用户(属主)读        :由用户(属主)写        :由(属)组成员读        :由(属)组成员写        :由其他用户读        :由其他用户写oflag由选择参数和权限参数组合而成。ipcperm结构的cuid和cgid成员分别设置为调用进程的有效用户ID和有效组ID这两个成员合称为创建者ID。ipcperm结构的uid和gid成员也分别设置为调用进程的有效用户ID和有效组ID这两个成员合称为属主ID。ipcperm结构中的seq成员是一个槽位使用情况序列号。该变量是一个由内核为在系统中的每个潜在的IPC对象维护的计数器。每当删除一个IPC对象时内核就递增相应的槽位号若溢出则循环回。这避免在短时间内重用IPC标识符。msqidds结构对于系统中的每个SystemV消息队列内核维护一个如下的结构:structmsqidds{    structipcpermmsgperm*operationpermissionstruct*    structmsg*msgfirst*ptrtofirstmessageonq*    structmsg*msglast*ptrtolastmessageonq*    unsignedshortmsgcbytes*current#bytesonq*    msgqnumtmsgqnum*#ofmessagesonq*    msglentmsgqbytes*max#ofbytesonq*    pidtmsglspid*pidoflastmsgsnd*    pidtmsglrpid*pidoflastmsgrcv*    timetmsgstime*lastmsgsndtime*    timetmsgrtime*lastmsgrcvtime*    timetmsgctime*lastchangetime*}msgget函数#include<sysmsgh>intmsgget(keytkey,intoflag)返回:成功时为非负标识符出错时为。用于创建一个新的SystemV消息队列或访问一个已经存在的消息队列。参数key和oflag的说明见前。返回值是一个整数标识符其他三个msg函数用它来指代该队列。当创建一个消息队列时msqidds结构的如下成员被初始化:        msgperm结构的uid和cuid被设置为当前进程的有效用户IDgid和cgid被设置为当前用户的有效组ID        oflag中的读写权限位存放在msgpermmode中        msgqnum、msglspid、msglrpid、msgstime和msgrtime被置为        msgctime被设置成当前时间        msgqbytes被设置为系统限制值。msgsnd函数#include<sysmsgh>intmsgsnd(intmsgid,constvoid*ptr,sizetlength,intflag)返回:成功时为出错时为。该函数用于往消息队列上放置一个消息。msgid是msgget返回的标识符ptr是一个结构指针该结构有如下的模板:structmsgbuf{    longmtype*messagetype,mustbe>*    charmtext*messagedata*}消息类型mtype必须大于因为非正消息类型有特殊的指示作用。length参数以字节为单位指定待发送消息的长度。这是位于长整数消息类型之后的用户自定义数据的长度该长度可以是。flag参数可以是也可以是IPCNOWAIT。IPCNOWAIT标志使得msgsnd调用非阻塞。当有如下情形之一时:   在指定的队列中已经有太多的字节(对应msqidds结构中的msgqbytes值)   在系统范围存在太多的消息。若设置了IPCNOWAIT则msgsnd立即返回返回一个EAGAIN错误。若未指定该标志则msgsnd阻塞直到:   具备存放新消息的空间   有msgid标识的消息队列被删除此时返回EIDRM错误   被信号中断此时返回EINTR错误。msgrcv函数#include<sysmsgh>ssizetmsgrcv(intmsqid,void*ptr,sizetlength,longtype,intflag)返回:成功时为读入缓冲区中数据的字节数出错时为。该函数从某个消息队列中读出一个消息。ptr参数指定所接收消息的存放位置。跟msgsnd一样该指针指向紧挨在真正的消息数据之前返回的长整数类型字段。length指定由ptr指向的缓冲区中数据部分的大小。这是该函数能返回的最大数据量。该长度不包含长整数类型字段。type指定希望从所给定的队列中读出什么样的消息:   type为返回队列中第一个消息。每个消息队列是作为一个FIFO链表维护的所以返回的是队列中最早的消息。   type大于返回其类型值为type的第一个消息。   type小于返回其类型值小于或等于type参数的绝对值的消息中类型值最小的第一个消息。flag参数指定所请求的消息不在队列中时怎么办。在没有消息时若设置了IPCNOWAIT标志则函数立即返回一个ENOMSG错误否则调用者阻塞知道如下某个时间发生:   有一个所请求类型的消息可获取   由msqid标识的消息队列被删除此时返回个EIDRM错误   被某个捕获的信号中断此时返回EINTR错误。msgctl函数#include<sysmsgh>intmsgctl(intmsqid,intcmd,structmsqidds*buf)返回:成功时为出错时为。该函数提供在一个消息队列上的各种控制操作。msgctl提供三个命令:        IPCRMID:从系统中删除由msqid指定的消息队列。当前在该队列上的任何消息都被丢弃。此时。第三个参数忽略不用。        IPCSET:给指定的消息队列设置其msqidds结构的以下四个成员:msgpermuid、msgpermgid、msgpermmode和msgpermqbytes。它们的值来自buff指向的结构中的相应成员。        IPCSTAT:通过buff参数给调用者返回所指定消息队列中的当前msqidds结构。在SystemV消息队列上使用select和pollSystemV消息队列通过标识符而不是描述字标识所以不能在消息队列上直接使用select和poll。解决问题的方法之一是:让服务器创建一个管道然后派生一个子进程由子进程阻塞在msgrcv调用中。当有消息准备好被处理时msgrcv返回子进程读出该消息并把消息写入管道。服务器父进程可能在管道以及一些网络连接上select。这种办法的负面效果是消息被处理了三次为避免此种情况父进程可以创建一个在它自身和子进程之间分享的共享内存区然后把管道用作父子进程见的一种标志。与网络编程相比SystemV消息队列的另一个遗失特性是无法窥探一个消息而这是recv、recvfrom和recvmsg函数的MSGPEEK标志提供的能力。semidds结构SystemV信号灯是信号灯集的概念:一个或多个信号灯构成一个集合。对于系统每个信号灯集内核维护如下的一个结构:structsemidds{    structipcpermsemperm*operationpermissionstruct*    structsem*sembase*ptrtofirstsemaphoreinset*    unsignedshortsemnsems*#ofsemaphoresinset*    timetsemotime*lastsemoptime*    timetsemctime*lastchangetime*}当前信号灯集中的每个信号灯对应一个sem结构。定义如下:structsem{    signedshortsemval*semaphoretextmapaddress*    pidtsempid*pidoflastoperation*    unsignedshortsemncnt*#awaitingsemval>cval*    unsignedshortsemzcnt*#awaitingsemval=*}semget函数#include<syssemh>intsemget(keytkey,intnsems,intoflag)返回:成功时为非负标识符出错时为。创建一个信号灯集或访问一个已存在的信号灯集。返回值是信号灯标识符供其他信号灯函数使用。nsems是集合中的信号灯数。如果不是创建一个信号灯集而只是访问已存在的集合则该参数可以指定为。一旦创建完毕一个信号灯集就不能改变其中的信号灯数。当实际操作为创建一个新的信号灯集时semidds结构的以下成员将被初始化:   semperm结构的uid和cuid被设置为调用进程的有效用户IDgid和cgid被设置为调用进程的有效组ID   oflag参数中的读写权限存入sempermmode中   semotime被设置为semctime被置为当前时间   semnsems被置为nsems参数的值   与该集合中每个信号灯关联的各个sem结构并不初始化。这些结构必须是在以SETVAL或SETALL命令调用semctl时初始化的。SystemV信号灯的创建和初始化需两次函数调用是一个致命的缺陷这会导致竞争状态的出现。解决竞争状态的方法是:当semget创建一个新的信号灯集时其semidds结构的semotime成员保证被设置为。该成员只是在semop调用成功时才被设置为当前值。在调用semget进行访问而不是创建时以IPCSTAT命令调用semctl然后等待semotime变为非零值。到时就可断定该信号灯已经被初始化而且对它初始化的进程已成功完成semop调用。所以创建该信号灯集的进程必须初始化它的值而且必须在任何其他进程可以使用该信号灯集之前调用semop。例子程序见:unpve:locklocksvsemc。semop函数#include<syssemh>intsemop(intsemid,structsembuf*opsptr,sizetnops)返回:成功时为出错时为。对一个或多个信号灯进行操作。opsptr指向如下结构模板的数组(该结构可能不止如下几个成员):structsembuf{    shrotsemnum*semaphorenumber:,,,nsems*    shortsemop*semaphoreoperation:<,,>*    shortsemflg*operationflags:,IPCNOWAIT,SEMUNDO*}nops参数指出结构数组中元素的个数。每个元素给目标信号灯集中某个信号灯指定一个操作。特定的信号灯由semnum指定semop指定特定的操作semflg指定非阻塞(IPCNOWAIT)、恢复等标志。在阻塞、非阻塞情况下返回的错误情况与其他SystemVIPC相同。semop函数由内核保证原子的执行内核或者完成所有操作或者什么也不做。semop操作的具体描述:        如果semop是正数其值就加到semval(信号灯的当前值)上这对应于释放由某个信号灯控制的资源。如果指定了SEMUNDO标志就从相应信号灯的semadj值中减掉semop的值。        如果semop是那么调用者希望等待到semval变为如果semval已经是则立即返回如果semval不为相应信号灯的semzcnt(等待semval变为的线程数)值就加调用线程阻塞到semval变为(那时semzcnt再减)。若指定了IPCNOWAIT则调用线程不会睡眠返回EAGAIN。        如果semop是负数那么调用者希望等待semval变为大于或等于semop的绝对值这对应于分配资源。如果semval大于或等于semop的绝对值则从semval中减掉semop的绝对值如果指定了SEMUNDO那么semop的绝对值就加到相应信号灯的semadj值上。如果semval小于semop的绝对值相应信号灯的semncnt值就加调用线程阻塞直到semval变为大于或等于semop的绝对值。若指定了IPCNOWAIT则调用线程不会睡眠返回EAGAIN。semadj称为指定信号灯针对调用进程的调整值。当调用进程终止时semadj的值就加到相应信号灯的semval上。若调用进程对某个信号灯的全部操作都指定SEMUNDO标志则该进程终止时该信号灯的值就会变得像根本没有运行过该进程一样这就是复旧(undo)的本意。semctl函数#include<syssemh>intsemctl(intsemid,intsemnum,intcmd,…*unionarg*)返回:成功时为非负值出错时为。对一个信号灯执行各种控制操作。semnum标识某个信号灯semnum仅仅用于GETVAL、SETVAL、GETNCNT、GETZCNT和GETPID命令。第四个参数是可选的它依赖于第三个参数cmd。它是一个联合:unionsemun{    intval*usedforSETVALonly*    structsemidds*buf*usedfroIPCSETandIPCSTAT*    ushort*array*usedforGETALLandSETALL*}该联合没有出现在任何系统头文件中由应用程序声明。而且它是以值传递的而不是以引用传递的。SystemV支持如下cmd值(除特别声明成功时返回失败返回):        GETVAL:把semval的当前值作为函数返回值返回。        SETVAL:把semval设置为argval。如果操作成功那么相应信号灯在所在进程中的调整值(semadj)将被置为。        GETPID:把sempid的当前值作为函数值返回。        GETNCNT:把semncnt的当前值作为函数值返回。        GETZCNT:把semzcnt的当前值作为函数值返回。        GETALL:返回所指定信号灯集的每个成员的semval值。这些值通过argarray指针返回。函数本身返回值为。注意调用者必须分配足够容纳所指定信号灯集中所有成员的semval值的一个unsignedshort整数数组然后把argarray设置成指向这个数组。        SETALL:设置所指定信号灯集中每个成员的semval值。这些值通过argarray数组指定。        IPCRMID:把由semid指定的信号灯集从系统中删除。        IPCSET:设置semidds结构中的以下三个成员:sempermuid、sempermgid和sempermmode。这些值来自由argbuf参数指向的结构中相应成员。semidds中的semctime成员也被设置为当前值。        IPCSTAT:通过argbuf参数返回当前的semidds结构。注意调用者必须首先分配一个semidds结构并把argbuf设置为指向这个结构。shmidds结构对于每个SystemV共享内存区内核维护如下的信息结构:structshmidds{    structipcpermshmperm*operationpermissionstruct*    sizetshmsegsz*sizeofsegmentinbytes*    pidtshmlpid*pidoflastshmop*    pidtshmcpid*pidofcreator*    shmatttshmnattch*current#attached*    shmattshmcnattch*incore#attached*    timetshmatime*lastshmattime*    timetshmdtime*lastshmdttime*    timetshmctime*lastchangetime*}shmget函数#include<sysshmh>intshmget(keytkey,sizetsize,intoflag)返回:成功时为共享内存区对象出错时为。函数创建一个尚未存在的共享内存区或者访问一个已存在的共享内存区。返回值是共享内存区标识符供其他函数使用。size参数以字节为单位指定内存的大小。当实际操作为创建一个新的内存区时必须指定一个不为的size值如果实际操作是访问一个已存在的共享内存区则size应为。当实际操作为创建一个新的内存区时该内存区被初始化为size个字节的。shmat函数#include<sysshmh>void*shmat(intshmid,constvoid*shmaddr,intflag)返回:成功时为映射区的其始地址出错时为。调用shmat将共享内存区附接到调用进程的地址空间。shmid是shmget的返回值。shmat的返回值是所指定的共享内存区在调用进程内的起始地址。确定此地址的规则如下:        如果shmaddr是空指针则系统替调用者选择地址。这是推荐(也是可移植性最好的)方法。        如果shmaddr非空则返回地址取决于调用者是否给flag参数指定了SHMRND值。如果SHMRND没有指定则共享内存区附接到由shmaddr指定的地址若指定SHMRND则附接到由shmaddr指定的地址向下舍入一个SHMLBA常值。LBA代表“低端边界地址(lowerboundaryaddress)。flag参数可以指定SHMRDONLY值它限定只读访问。shmdt函数#include<sysshmh>intshmdt(constvoid*shmaddr)返回:成功时为出错时为。调用shmdt断开与共享内存区的连接。当一个进程终止时它的所有当前附接着的共享内存区都自动断接掉。shmctl函数#include<sysshmh>intshmctl(intshmid,intcmd,structshmidds*buff)返回:成功时为出错时为。函数提供三个命令:        IPCRMID:从系统中删除由shmid标识的共享内存区并拆除它。        IPCSET:给所指定的共享内存区设置其shmidds结构的以下三个成员:shmpermuid、shmpermgid和shmpermmode它们的值来自参数中的相应成员。shmctime的值用当前时间替换。        IPCSTAT:向调用者返回所指定共享内存区的当前shmidds结构。mmap函数#include<sysmmanh>void*mmap(void*addr,sizetlen,intprot,intflags,intfd,offtoffset)返回:成功时为被映射区的起始地址出错时为MAPFAILD。mmap函数把一个文件或一个Posix共享内存区对象映射到调用进程的地址空间。使用该函数有三个目的:        使用普通文件以提供内存映射        使用特殊文件以提供匿名内存映射        使用shmopen以提供无亲缘关系进程间的Posix共享内存区。其中addr可以指定为描述字fd应被映射到的进程内空间的起始地址。它通常被指定为一个空指针让内核自己去选择起始地址。Len是映射到调用进程地址空间的字节数它从被映射文件开头起offset个字节处开始算。内存映射区的保护由prot参数指定它使用如下的常值。该参数的常见值是PROTREAD|PROTWRITE:        PROTREAD:数据可读        PROTWRITE:数据可写        PROTEXEC:数据可执行        PROTNONE:数据不可访问。flags使用如下的常值。MAPSHARED或MAPPRIVATE这两个标志必须指定一个并可有选择的或上MAPFIXED。MAPPRIVATE的含义是调用进程对被映射数据所作的修改只对该进程可见而不改变其底层支撑对象(或者是一个文件对象或者是一个共享内存区对象)。MAPSHARED的含义则是调用进程对被映射数据所作的修改对于共享该对象的所有进程都可见而且确实改变了其底层支撑对象。从移植性上考虑MAPFIXED不应该指定:        MAPSHARED:变动是共享        MAPPRIVATE:变动是私自的        MAPFIXED:准确的解释addr参数。mmap成功返回后fd参数可以关闭。该操作对于由mmap建立的映射关系没有影响。父子进程之间共享内存区的方法之一是父进程在调用fork前指定MAPSHARED调用mmap。Posix保证父进程中的内存映射关系存留到子进程中而且父进程所作的修改子进程能看到反过来也一样。不是所有的文件都能进行内存映射。如把一个访问终端或套接口的描述字映射到内存将导致mmap返回一个错误。内存映射区的大小(mmap的第二个参数)可以与文件的大小不同。但是内核跟踪着被内存映射的底层支撑对象的大小而且我们总是能访问在当前文件大小以内又在内存映射区以内的那些字节。munmap函数#include<sysmmanh>intmunmap(void*addr,sizetlen)返回:成功时为出错时为。其中addr是mmap返回的地址len是映射区的大小。从进程地址空间删除一个映射关系。之后再次访问这些地址将导致向调用进程产生一个SIGSEGV信号。如果映射区用MAPPRIVATE标志映射那么调用进程对它所作的变动都被丢弃。msync函数#include<sysmmanh>intmsync(void*addr,sizetlen,intflags)返回:成功时为出错时为。内核的虚存算法保持内存映射文件(一般在硬盘上)与内存映射区(在内存中)的同步(使用了MAPSHARED)如果我们修改了内存映射到某个文件的内存区中某个位置的内容那么内核将在稍后某个时刻相应的更新文件。如果我们希望确信硬盘上的文件内容与内存映射区中的内容一致则调用msync来执行这种同步。其中addr和len参数通常指代内存中的整个内存映射区不过也可指定该内存区的一个子集。flags是如下常值的组合:        MSASYNC:执行异步写        MSSYNC:执行同步写        MSINVALIDATE:是高速缓存的数据失效。MSASYNC和MSSYNC这两个值必须指定一个但不能都指定。两者的差别是一旦写操作已由内核排入队列MSASYNC即返回而MSSYNC则要等到写操作完成后返回。如果还指定了MSINVALIDATE那么与其最终拷贝不一致的文件数据的所有内存中拷贝都失效后续的引用将从文件中取得数据。匿名内存映射如果调用mmap的目的是提供一个即将穿越fork由父子进程共享的映射内存区则可以不用创建一个文件在open它等一系列操作。具体依赖于实现:        BSD提供匿名内存映射它彻底避免了文件的创建和打开。方法是把mmap的flags参数指定为MAPSHARED|MAPANON把fd参数指定为offset参数被忽略。这样的内存区初始化为。        SVR提供devzero设备文件我们open它之后可在mmap调用中使用得到的描述字。从该设备读时返回的字节全为写往该设备的任何字节则被丢弃。(许多源自Berkeley的实现也支持devzero如SunOsx和BSDOS)。例子见unpve:shmincrmapanonc和shmincrdevzeroc。发表于年月日 :: |评论()|编辑|举报|收藏旧一篇:怎样学好C语言 | 新一篇:Linux进程间通讯之信号量专区推荐

精彩专题

职业精品

上传我的资料

热门资料

资料评价:

/ 26
所需积分:5 立即下载

意见
反馈

返回
顶部

Q