📄 program-multi-fork.html
字号:
<br>语法:#include
<br>void (*signal(sig,disp))(int)
<br>int sig;
<br>void (*disp)(int);
<p>void (*sigset(sig,disp))(int)
<br>int sig;
<br>void (*disp)(int);
<p>int sighold(sig)
<br>int sig;
<p>int sigrelse(sig)
<br>int sig;
<p>int sigignore(sig)
<br>int sig;
<p>int sigpause(sig)
<br>int sig;
<br>说明:这些系统调用提供了应用程序对指定信号的简单的信号处理.
<br>signal()和sigset()用于修改信号定位.参数sig指定信号(除了
<br>SIGKILL和SIGSTOP,这两种信号由系统处理,用户程序不能捕捉到).
<br>disp指定新的信号定位,即新的信号处理函数指针.可以为
<br>SIG_IGN,SIG_DFL或信号句柄地址.
<br>若使用signal(),disp是信号句柄地址,sig不能为SIGILL,SIGTRAP
<br>或SIGPWR,收到该信号时,系统首先将重置sig的信号句柄为SIG_DFL,
<br>然后执行信号句柄.
<br>若使用sigset(),disp是信号句柄地址,该信号时,系统首先将该
<br>信号加入调用进程的信号掩码中,然后执行信号句柄.当信号句柄
<br>运行结束
<br>后,系统将恢复调用进程的信号掩码为信号收到前的状态.另外,
<br>使用sigset()时,disp为SIG_HOLD,则该信号将会加入调用进程的
<br>信号掩码中而信号的定位不变.
<br>sighold()将信号加入调用进程的信号掩码中.
<br>sigrelse()将信号从调用进程的信号掩码中删除.
<br>sigignore()将信号的定位设置为SIG_IGN.
<br>sigpause()将信号从调用进程的信号掩码中删除,同时挂起调用
<br>进程直到收到信号.
<br>若信号SIGCHLD的信号定位为SIG_IGN,则调用进程的子进程在终
<br>止时不会变成僵死进程.调用进程也不用等待子进程返回并做相
<br>应处理.
<br>返回值:调用成功则signal()返回最近调用signal()设置的disp的值.
<br>否则返回SIG_ERR.
<br>例子一:设置用户自己的信号中断处理函数,以SIGINT信号为例:
<br>int flag=0;
<br>void myself()
<br>{
<br>flag=1;
<br>printf("get signal SIGINT\n");
<br>/*若要重新设置SIGINT信号中断处理函数为本函数则执行以
<br>*下步骤*/
<br>void (*a)();
<br>a=myself;
<br>signal(SIGINT,a);
<br>flag=2;
<br>}
<br>main()
<br>{
<br>while (1) {
<br>sleep(2000); /*等待中断信号*/
<br>if (flag==1) {
<br>printf("skip system call sleep\n");
<br>exit(0);
<br>}
<br>if (flag==2) {
<br>printf("skip system call sleep\n");
<br>printf("waiting for next signal\n");
<br>}
<br>}
<br>}
<br>11.kill()
<br>功能:向一个或一组进程发送一个信号.
<br>语法:#include
<br>#include
<br>int kill(pid,sig);
<br>pid_t pid;
<br>int sig;
<br>说明:本系统调用向一个或一组进程发送一个信号,该信号由参数sig指
<br>定,为系统给出的信号表中的一个.若为0(空信号)则检查错误但
<br>实际上并没有发送信号,用于检查pid的有效性.
<br>pid指定将要被发送信号的进程或进程组.pid若大于0,则信号将
<br>被发送到进程号等于pid的进程;若pid等于0则信号将被发送到所
<br>有的与发送信号进程同在一个进程组的进程(系统的特殊进程除
<br>外);若pid小于-1,则信号将被发送到所有进程组号与pid绝对值
<br>相同的进程;若pid等于-1,则信号将被发送到所有的进程(特殊系
<br>统进程除外).
<br>信号要发送到指定的进程,首先调用进程必须有对该进程发送信
<br>号的权限.若调用进程有合适的优先级则具备有权限.若调用进程
<br>的实际或有效的UID等于接收信号的进程的实际UID或用setuid()
<br>系统调用设置的UID,或sig等于SIGCONT同时收发双方进程的会话
<br>号相同,则调用进程也有发送信号的权限.
<br>若进程有发送信号到pid指定的任何一个进程的权限则调用成功,
<br>否则调用失败,没有信号发出.
<br>返回值:调用成功则返回0,否则返回-1.
<br>例子:假设前一个例子进程号为324,现向它发一个SIGINT信号,让它做
<br>信号处理:
<br>kill((pid_t)324,SIGINT);
<br>12.alarm()
<br>功能:设置一个进程的超时时钟.
<br>语法:#include
<br>unsigned int alarm(sec)
<br>unsigned int sec;
<br>说明:指示调用进程的超时时钟在指定的时间后向调用进程发送一个
<br>SIGALRM信号.设置超时时钟时时间值不会被放入堆栈中,后一次
<br>设置会把前一次(还未到超时时间)冲掉.
<br>若sec为0,则取消任何以前设置的超时时钟.
<br>fork()会将新进程的超时时钟初始化为0.而当一个进程用exec()
<br>族系统调用新的执行文件时,调用前设置的超时时钟在调用后仍
<br>有效.
<br>返回值:返回上次设置超时时钟后到调用时还剩余的时间秒数.
<br>例子:int flag=0;
<br>void myself()
<br>{
<br>flag=1;
<br>printf("get signal SIGALRM\n");
<br>/*若要重新设置SIGALRM信号中断处理函数为本函数则执行
<br>*以下步骤*/
<br>void (*a)();
<br>a=myself;
<br>signal(SIGALRM,a);
<br>flag=2;
<br>}
<br>main()
<br>{
<br>alarm(100); /*100秒后发超时中断信号*/
<br>while (1) {
<br>sleep(2000); /*等待中断信号*/
<br>if (flag==1) {
<br>printf("skip system call sleep\n");
<br>exit(0);
<br>}
<br>if (flag==2) {
<br>printf("skip system call sleep\n");
<br>printf("waiting for next signal\n");
<br>}
<br>}
<br>}
<br>13.msgsnd()
<br>功能:发送消息到指定的消息队列中.
<br>语法:#include
<br>#include
<br>#include
<br>int msgsnd(msqid,msgp,msgsz,msgflg)
<br>int msqid;
<br>void *msgp;
<br>size_t msgsz;
<br>int msgflg;
<br>说明:发送一个消息到由msqid指定消息队列标识号的消息队列.
<br>参数msgp指向一个用户定义的缓冲区,并且缓冲区的第一个域应
<br>为长整型,指定消息类型,其他数据放在缓冲区的消息中其他正文
<br>区内.下面是消息元素定义:
<br>long mtype;
<br>char mtext[];
<br>mtype是一个整数,用于接收进程选择消息类型.
<br>mtext是一个长度为msgsz字节的任何正文,参数msgsz可从0到系
<br>统允许的最大值间变化.
<br>msgflg指定操作行为:
<br>. 若(msgflg&IPC_NOWAIT)是真的,消息并不是被立即发送而调用
<br>进程会立即返回.
<br>. 若(msgflg&IPC_NOWAIT)不是真的,则调用进程会被挂起直到下
<br>面情况之一发生:
<br>* 消息被发送出去.
<br>* 消息队列标志被系统删除.系统调用返回-1.
<br>* 调用进程接收到一个未被忽略的中断信号,调用进程继续
<br>执行或被终止.
<br>调用成功后,对应指定的消息队列的相关结构做如下动作:
<br>. 消息数(msg_qnum)加1.
<br>. 消息队列最近发送进程号(msg_lspid)改为调用进程号.
<br>. 消息队列发送时间(msg_stime)改为当前系统时间.
<br>以上信息可用命令ipcs -a看到.
<br>返回值:成功则返回0,否则返回-1.
<br>14.msgrcv()
<br>功能:从消息队列中取得指定类型的消息.
<br>语法:#include
<br>#include
<br>#include
<br>int msgrcv(msqid,msgp,msgsz,msgtyp,msgflg)
<br>int msqid;
<br>void *msgp;
<br>int msgsz;
<br>long msgtyp;
<br>int msgflg;
<br>说明:本系统调用从由msqid指定的消息队列中读取一个由msgtyp指定
<br>类型的消息到由msgp指向的缓冲区中,同样的,该缓冲区的结构如
<br>前所述,包括消息类型和消息正文.msgsz为可接收的消息正文的
<br>字节数.若接收到的消息正文的长度大于msgsz,则会被截短到
<br>msgsz字节为止(当消息标志msgflg&MSG_NOERROR为真时),截掉的
<br>部份将被丢失,而且不通知消息发送进程.
<br>msgtyp指定消息类型:
<br>. 为0则接收消息队列中第一个消息.
<br>. 大于0则接收消息队列中第一个类型为msgtyp的消息.
<br>. 小于0则接收消息队列中第一个类型值不小于msgtyp绝对值且
<br>类型值又最小的消息.
<br>msgflg指定操作行为:
<br>. 若(msgflg&IPC_NOWAIT)是真的,调用进程会立即返回,若没有
<br>接收到消息则返回值为-1,errno设置为ENOMSG.
<br>. 若(msgflg&IPC_NOWAIT)不是真的,则调用进程会被挂起直到下
<br>面情况之一发生:
<br>* 队列中的消息的类型是有效的.
<br>* 消息队列标志被系统删除.系统调用返回-1.
<br>* 调用进程接收到一个未被忽略的中断信号,调用进程继续
<br>执行或被终止.
<br>调用成功后,对应指定的消息队列的相关结构做如下动作:
<br>. 消息数(msg_qnum)减1.
<br>. 消息队列最近接收进程号(msg_lrpid)改为调用进程号.
<br>. 消息队列接收时间(msg_rtime)改为当前系统时间.
<br>以上信息可用命令ipcs -a看到.
<br>返回值:调用成功则返回值等于接收到实际消息正文的字节数.
<br>不成功则返回-1.
<br>15.msgctl()
<br>功能:消息控制操作
<br>语法:#include
<br>#include
<br>#include
<br>int msgctl(msqid,cmd,buf)
<br>int msqid,cmd;
<br>struct msqid_ds *buf;
<br>说明:本系统调用提供一系列消息控制操作,操作动作由cmd定义,以下
<br>cmd定义值表明了各操作动作的定义.
<br>. IPC_STAT:将msqid相关的数据结构中各个元素的当前值放入由
<br>buf指向的结构中.
<br>. IPC_SET:将msqid相关的数据结构中的下列元素设置为由buf指
<br>向的结构中的对应值.
<br>msg_perm.uid
<br>msg_perm.gid
<br>msg_perm.mode
<br>msg_qbytes
<br>本命令只能由有效UID等于msg_perm.cuid或msg_perm.uid的
<br>进程或有效UID有合适权限的进程操作.只有具有合适权限的
<br>用户才能增加msg_qbytes的值.
<br>. IPC_RMID:删除由msqid指示的消息队列.将它从系统中删除并
<br>破坏相关的数据结构.
<br>本命令只能由有效UID等于msg_perm.cuid或msg_perm.uid的
<br>进程或有效UID有合适权限的进程操作.
<br>返回值:调用成功则返回值为0,否则为-1.
<br>16.msgget()
<br>功能:取得一个消息队列.
<br>语法:#include
<br>#include
<br>#include
<br>int msgget(key,msgflg)
<br>key_t key;
<br>int msgflg;
<br>说明:本系统调用返回与参数key相关的消息队列的标识符.
<br>若以下事实成立,则与消息队列相关的标识符和数据结构将被创
<br>建出来:
<br>. 若参数key等于IPC_PRIVATE.
<br>. 若参数key没有一个已存在的消息队列标识符与之相关,同时值
<br>(msgflg&IPC_CREAT)为真.
<br>创建消息队列时,与新的消息队列标识符相关的数据结构将被初
<br>始化为如下:
<br>. msg_perm.cuid和msg_perm.uid设置为调用进程的有效UID.
<br>. msg_perm.cgid和msg_perm.gid设置为调用进程的有效GID.
<br>. msg_perm.mode访问权限比特位设置为msgflg访问权限比特位.
<br>. msg_qnum,msg_lspid,msg_lrpid,msg_stime,msg_rtime设置为0.
<br>. msg_ctime设置为当前系统时间.
<br>. msg_qbytes设置为系统允许的最大值.
<br>返回值:调用成功则返回一非0值,称为消息队列标识符;否则返回值为-1.
<br>例子:本例将包括上述所有消息队列操作的系统调用:
<br>#define RKEY 0x9001L /*读消息队列的KEY值*/
<br>#define WKEY 0x9002L /*写消息队列的KEY值*/
<br>#define MSGFLG 0666 /*消息队列访问权限*/
<br>#define IPC_WAIT 0 /*等待方式在include文件中未定义*/
<br>int rmsqid; /*读消息队列标识符*/
<br>int wmsqid; /*写消息队列标识符*/
<br>struct msgbuf {
<br>long mtype;
<br>char mtext[200];
<br>} buf;
<br>/*若读消息队列已存在就取得标识符,否则则创建并取得标识符*/
<br>if ((rmsqid=msgget(RKEY,MSGFLG|IPC_CREAT))<0) {
<br>printf("get read message queue failed\n");
<br>exit(1);
<br>}
<br>/*若写消息队列已存在则失败,若不存在则创建并取得标识符*/
<br>if ((wmsqid=msgget(WKEY,
<br>MSGFLG|IPC_CREAT|IPC_TRUNC))<0) {
<br>printf("get write message queue failed\n");
<br>exit(2);
<br>}
<br>/*接收所有类型的消息*/
<br>if (msgrcv(rmsqid,&buf,sizeof(struct msgbuf)-sizeof(long),
<br>0L,IPC_WAIT)>0)
<br>printf("get %ld type message from queue:%s\n",
<br>buf.mtype,buf.mtext);
<br>else {
<br>printf("get message failed\n");
<br>exit(3);
<br>}
<br>buf.mtype=3L
<br>if (msgsnd(wmsqid,&buf,sizeof(struct msgbuf)-sizeof(long),
<br>IPC_NOWAIT)>0)
<br>printf("send message OK\n");
<br>else {
<br>printf("send message failed\n");
<br>exit(4);
<br>}
<br>msgctl(wmsqid,IPC_RMID,(struct msqid *)NULL);
<br>17.shmat()
<br>功能:联接共享内存的操作.
<br>语法:#include
<br>#include
<br>#include
<br>void *shmat(shmid,shmaddr,shmflg)
<br>int shmid;
<br>void *shmaddr;
<br>int shmid;
<br>说明:将由shmid指示的共享内存联接到调用进程的数据段中.被联接的
<br>段放在地址,该地址由以下准则指定:
<br>. 若shmaddr等于(void *)0,则段联接到由系统选择的第一个可
<br>用的地址上.
<br>. 若shmaddr不等于(void *)0同时(shmflg&SHM_RND)值为真,则
<br>段联接到由(shmaddr-(shmaddr%SHMLBA))给出的地址上.
<br>. 若shmaddr不等于(void *)0同时(shmflg&SHM_RND)值为假,则
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -