当前位置: 首页 > news >正文

[每日一点]msgsnd函数代码跟踪

今天有一同事问我,如果msgsnd函数的最后一个flag如果直接置0,调用该函数会是什么结果!

我不太清楚是怎样的,还是直接看代码:

msgsnd是一个系统调用,所以它在glibc中只是一个桩函数:
\glibc\glibc-2.4.src\sysvipc\msgsnd.c
int
msgsnd (msqid, msgp, msgsz, msgflg)
     int msqid;
     const void *msgp;
     size_t msgsz;
     int msgflg;
{
  __set_errno (ENOSYS);
  return -1;
}

stub_warning (msgsnd)

而在内核中的实现函数:

~\kernel\linux-2.6.21.1.src\ipc\msg.c

ContractedBlock.gif ExpandedBlockStart.gif
ContractedBlock.gif ExpandedBlockStart.gif Code
  1asmlinkage long
  2sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
  3ExpandedBlockStart.gifContractedBlock.gif{
  4 long mtype;
  5
  6 if (get_user(mtype, &msgp->mtype))
  7  return -EFAULT;
  8 return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
  9}

 10
 11
 12
 13
 14long do_msgsnd(int msqid, long mtype, void __user *mtext,
 15  size_t msgsz, int msgflg)
 16ExpandedBlockStart.gifContractedBlock.gif{
 17 struct msg_queue *msq;
 18 struct msg_msg *msg;
 19 int err;
 20 struct ipc_namespace *ns;
 21
 22 ns = current->nsproxy->ipc_ns;
 23
 24 if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0)
 25  return -EINVAL;
 26 if (mtype < 1)
 27  return -EINVAL;
 28
 29 msg = load_msg(mtext, msgsz);
 30 if (IS_ERR(msg))
 31  return PTR_ERR(msg);
 32
 33 msg->m_type = mtype;
 34 msg->m_ts = msgsz;
 35
 36 msq = msg_lock(ns, msqid);
 37 err = -EINVAL;
 38 if (msq == NULL)
 39  goto out_free;
 40
 41 err= -EIDRM;
 42 if (msg_checkid(ns, msq, msqid))
 43  goto out_unlock_free;
 44
 45ExpandedSubBlockStart.gifContractedSubBlock.gif for (;;) {
 46  struct msg_sender s;
 47
 48  err = -EACCES;
 49  if (ipcperms(&msq->q_perm, S_IWUGO))
 50   goto out_unlock_free;
 51
 52  err = security_msg_queue_msgsnd(msq, msg, msgflg);
 53  if (err)
 54   goto out_unlock_free;
 55
 56  if (msgsz + msq->q_cbytes <= msq->q_qbytes &&
 57ExpandedSubBlockStart.gifContractedSubBlock.gif    1 + msq->q_qnum <= msq->q_qbytes) {
 58   break;
 59  }

 60
 61ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//* queue full, wait: */
 62ExpandedSubBlockStart.gifContractedSubBlock.gif  if (msgflg & IPC_NOWAIT) {
 63   err = -EAGAIN;
 64   goto out_unlock_free;
 65  }

 66  ss_add(msq, &s);
 67  ipc_rcu_getref(msq);
 68  msg_unlock(msq);
 69  schedule();
 70
 71  ipc_lock_by_ptr(&msq->q_perm);
 72  ipc_rcu_putref(msq);
 73ExpandedSubBlockStart.gifContractedSubBlock.gif  if (msq->q_perm.deleted) {
 74   err = -EIDRM;
 75   goto out_unlock_free;
 76  }

 77  ss_del(&s);
 78
 79ExpandedSubBlockStart.gifContractedSubBlock.gif  if (signal_pending(current)) {
 80   err = -ERESTARTNOHAND;
 81   goto out_unlock_free;
 82  }

 83 }

 84
 85 msq->q_lspid = current->tgid;
 86 msq->q_stime = get_seconds();
 87
 88ExpandedSubBlockStart.gifContractedSubBlock.gif if (!pipelined_send(msq, msg)) {
 89ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//* noone is waiting for this message, enqueue it */
 90  list_add_tail(&msg->m_list, &msq->q_messages);
 91  msq->q_cbytes += msgsz;
 92  msq->q_qnum++;
 93  atomic_add(msgsz, &msg_bytes);
 94  atomic_inc(&msg_hdrs);
 95 }

 96
 97 err = 0;
 98 msg = NULL;
 99
100out_unlock_free:
101 msg_unlock(msq);
102out_free:
103 if (msg != NULL)
104  free_msg(msg);
105 return err;
106}

107
108
Code
  1asmlinkage long
  2sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
  3ExpandedBlockStart.gifContractedBlock.gif{
  4 long mtype;
  5
  6 if (get_user(mtype, &msgp->mtype))
  7  return -EFAULT;
  8 return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
  9}
 10
 11
 12
 13
 14long do_msgsnd(int msqid, long mtype, void __user *mtext,
 15  size_t msgsz, int msgflg)
 16ExpandedBlockStart.gifContractedBlock.gif{
 17 struct msg_queue *msq;
 18 struct msg_msg *msg;
 19 int err;
 20 struct ipc_namespace *ns;
 21
 22 ns = current->nsproxy->ipc_ns;
 23
 24 if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0)
 25  return -EINVAL;
 26 if (mtype < 1)
 27  return -EINVAL;
 28
 29 msg = load_msg(mtext, msgsz);
 30 if (IS_ERR(msg))
 31  return PTR_ERR(msg);
 32
 33 msg->m_type = mtype;
 34 msg->m_ts = msgsz;
 35
 36 msq = msg_lock(ns, msqid);
 37 err = -EINVAL;
 38 if (msq == NULL)
 39  goto out_free;
 40
 41 err= -EIDRM;
 42 if (msg_checkid(ns, msq, msqid))
 43  goto out_unlock_free;
 44
 45ExpandedSubBlockStart.gifContractedSubBlock.gif for (;;) {
 46  struct msg_sender s;
 47
 48  err = -EACCES;
 49  if (ipcperms(&msq->q_perm, S_IWUGO))
 50   goto out_unlock_free;
 51
 52  err = security_msg_queue_msgsnd(msq, msg, msgflg);
 53  if (err)
 54   goto out_unlock_free;
 55
 56  if (msgsz + msq->q_cbytes <= msq->q_qbytes &&
 57ExpandedSubBlockStart.gifContractedSubBlock.gif    1 + msq->q_qnum <= msq->q_qbytes) {
 58   break;
 59  }
 60
 61ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//* queue full, wait: */
 62ExpandedSubBlockStart.gifContractedSubBlock.gif  if (msgflg & IPC_NOWAIT) {
 63   err = -EAGAIN;
 64   goto out_unlock_free;
 65  }
 66  ss_add(msq, &s);
 67  ipc_rcu_getref(msq);
 68  msg_unlock(msq);
 69  schedule();
 70
 71  ipc_lock_by_ptr(&msq->q_perm);
 72  ipc_rcu_putref(msq);
 73ExpandedSubBlockStart.gifContractedSubBlock.gif  if (msq->q_perm.deleted) {
 74   err = -EIDRM;
 75   goto out_unlock_free;
 76  }
 77  ss_del(&s);
 78
 79ExpandedSubBlockStart.gifContractedSubBlock.gif  if (signal_pending(current)) {
 80   err = -ERESTARTNOHAND;
 81   goto out_unlock_free;
 82  }
 83 }
 84
 85 msq->q_lspid = current->tgid;
 86 msq->q_stime = get_seconds();
 87
 88ExpandedSubBlockStart.gifContractedSubBlock.gif if (!pipelined_send(msq, msg)) {
 89ExpandedSubBlockStart.gifContractedSubBlock.gif  /**//* noone is waiting for this message, enqueue it */
 90  list_add_tail(&msg->m_list, &msq->q_messages);
 91  msq->q_cbytes += msgsz;
 92  msq->q_qnum++;
 93  atomic_add(msgsz, &msg_bytes);
 94  atomic_inc(&msg_hdrs);
 95 }
 96
 97 err = 0;
 98 msg = NULL;
 99
100out_unlock_free:
101 msg_unlock(msq);
102out_free:
103 if (msg != NULL)
104  free_msg(msg);
105 return err;
106}
107
108

security_msg_queue_msgsnd函数是调用一个钩子函数,之后没有对flag进行处理。所以,flag只在这个函数中有效:

即,只有在队列满,且标志位与IPC_NOWAIT或时不为0,则返回错误,否则没有什么影响。如果为0时,与IPC_NOWAIT取或运算显然为不0,所以会阻塞在这里,直到队列可用!

 

 

相关文章:

  • 硬币
  • 数字化管理(Digital Management)
  • 【生活】2017 开始!
  • UNIX IO---再谈文件描述符
  • HTML5 拖放(Drag 和 Drop)详解与实例
  • ⒍环境变量
  • 清北学堂总结(未完待续。。。。。。。)
  • 类QQ右下角弹出消息对话框(jQuery插件)
  • Struts2教程3:struts.xml常用配置解析
  • 如何安装 gearmand 及对应的 php 扩展
  • [osgearth]通过API创建一个earth模型
  • 我的博客的第一篇文章
  • 八数码问题
  • 网络工程师--Vlan
  • 设计中的同理心
  • 【附node操作实例】redis简明入门系列—字符串类型
  • CEF与代理
  • create-react-app项目添加less配置
  • ECMAScript入门(七)--Module语法
  • EOS是什么
  • Hexo+码云+git快速搭建免费的静态Blog
  • JS 面试题总结
  • LintCode 31. partitionArray 数组划分
  • npx命令介绍
  • Python_OOP
  • Rancher-k8s加速安装文档
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 初探 Vue 生命周期和钩子函数
  • 近期前端发展计划
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 深度学习在携程攻略社区的应用
  • 深入浅出webpack学习(1)--核心概念
  • 数据结构java版之冒泡排序及优化
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 用jquery写贪吃蛇
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • # 数论-逆元
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #LLM入门|Prompt#3.3_存储_Memory
  • (6)STL算法之转换
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (转)项目管理杂谈-我所期望的新人
  • .gitignore文件—git忽略文件
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .NET CORE Aws S3 使用
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET Micro Framework 4.2 beta 源码探析
  • .NET Project Open Day(2011.11.13)
  • .NET 使用 XPath 来读写 XML 文件
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .NET6使用MiniExcel根据数据源横向导出头部标题及数据
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • .Net程序猿乐Android发展---(10)框架布局FrameLayout