//若当前消息的类型码小
//于leastp的类型码 leastp = tmsg; //将临时当前消息指针tmsg赋值给leastp
if (leastp && leastp->msg_type <= - msgtyp) //若leastp存在且其指向
//消息的类型码小于给定类型码的绝对值
nmsg = leastp; //将leastp赋值给当前指针nmsg
}
if (nmsg) { /* done finding a message */ //如果其中存在符合类型的消息
if ((msgsz < nmsg->msg_ts) && !(msgflg & MSG_NOERROR)) {
return –E2BIG;
//若消息允许大小(msgsz)小于消息队列中特定消息的大小
}
msgsz = (msgsz > nmsg->msg_ts)? Nmsg->msg_ts : msgsz; //在消息允许大小msgsz和消息队列中特定消息大小
//并且没有设置MSG_NOERROR则取消息失败
nmsg->msg_ts
//取较大的值赋值给msgsz
if (nmsg == msq->msg_first) //若所取消息为消息队列头
msq->msg_first = nmsg->msg_next;
//则将nmsg->msg_next重新置为消息队列头
else { //若所取消息不是消息队列头
for (tmsg = msq->msg_first; tmsg; tmsg = tmsg->msg_next)
if (tmsg->msg_next == nmsg)
}
//循环搜索到要取消息的前一个指针tmsg
break;
tmsg->msg_next = nmsg->msg_next; //重新设置msg_next指针域
if (nmsg == msq->msg_last)//若所取消息是消息队列尾
msq->msg_last = tmsg; //重新设置msg_last指针域
if (!(--msq->msg_qnum)) //若取出消息后队列中已无消息
msq->msg_last = msq->msg_first = NULL; //设队列首与队列尾为NULL
msq->msg_rtime = CURRENT_TIME;//取消息时间更新为
//当前时间
msq->msg_lrpid = current->pid; //取消息进程号更
新为当前进程号
msgbytes -= nmsg->msg_ts; //全局变量msgbytes用来统计使用的消息字节的大小
//减少相应的字节
msghdrs--; //全局变量msghdrs用来统计小心队列的
个数,加1
数减少
wake_up (&msq->wwait);
msq->msg_cbytes -= nmsg->msg_ts; //队列中消息字节
//唤醒所有在该消息队列上等待的写消息进程
if (put_user (nmsg->msg_type, &msgp->mtype) ||
copy_to_user (msgp->mtext, nmsg->msg_spot, msgsz)) //将消息赋值到用户空间
msgsz = -EFAULT;
kfree(nmsg); //释放空间
上阻塞
}
return msgsz; //返回取得消息的大小
} else { /* did not find a message */ //若没有找到符合消息类型的消息
if (msgflg & IPC_NOWAIT) { //若设置IPC_NOWAIT return –ENOMSG; //则返回错误代码 }
if (signal_pending(current)) {//有信号要调用当前进程 }
interruptible_sleep_on (&msq->rwait);//让该进程在读进程
return –EINTR;
}
} /* end while */
return -1; //返回-1表示接收失败
4.5 函数sys_msgctl的分析 (李锐 负责)
4.5.1 代码及注释
asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) //msqid参数指定了一个消息队列,cmd指出sys_msgctl函数应该对它如何操作。 //需不需要buf取决于cmd,而且即使当它被使用时它的含义也将随情况的不同而不同。
{ int id, err = -EINVAL;
struct msqid_ds *msq; struct msqid_ds tbuf; struct ipc_perm *ipcp;
lock_kernel();//do { } while(0)
//加锁
if (msqid < 0 || cmd < 0)
//检查参数,如果参数错误就进行出错处理
goto out;
err = -EFAULT;
//根据cmd的不同进行不同的处理 switch (cmd) { case IPC_INFO: case MSG_INFO:
//返回所需要的信息到指定的结构struct msginfo中 {
struct msginfo msginfo;
/* buffer for msgctl calls IPC_INFO, MSG_INFO */ msginfo.msgmni = MSGMNI; msginfo.msgmax = MSGMAX; msginfo.msgmnb = MSGMNB; msginfo.msgmap = MSGMAP; msginfo.msgpool = MSGPOOL; msginfo.msgtql = MSGTQL; msginfo.msgssz = MSGSSZ; msginfo.msgseg = MSGSEG; if (cmd == MSG_INFO) {
//假如cmd是MSG_INFO而不是IPC_INFO时,还要包括一些额外信息 }
msginfo.msgpool = used_queues; msginfo.msgmap = msghdrs; msginfo.msgtql = msgbytes; if (!buf)
goto out;//返回
相关推荐: