zoukankan      html  css  js  c++  java
  • IPC之msgutil.c源码解读

    // SPDX-License-Identifier: GPL-2.0-or-later
    /*
     * linux/ipc/msgutil.c
     * Copyright (C) 1999, 2004 Manfred Spraul
     */
    
    #include <linux/spinlock.h>
    #include <linux/init.h>
    #include <linux/security.h>
    #include <linux/slab.h>
    #include <linux/ipc.h>
    #include <linux/msg.h>
    #include <linux/ipc_namespace.h>
    #include <linux/utsname.h>
    #include <linux/proc_ns.h>
    #include <linux/uaccess.h>
    #include <linux/sched.h>
    
    #include "util.h"
    
    DEFINE_SPINLOCK(mq_lock);
    
    /*
     * The next 2 defines are here bc this is the only file
     * compiled when either CONFIG_SYSVIPC and CONFIG_POSIX_MQUEUE
     * and not CONFIG_IPC_NS.
     */
    struct ipc_namespace init_ipc_ns = {
    	.count		= REFCOUNT_INIT(1),
    	.user_ns = &init_user_ns,
    	.ns.inum = PROC_IPC_INIT_INO,
    #ifdef CONFIG_IPC_NS
    	.ns.ops = &ipcns_operations,
    #endif
    };
    
    struct msg_msgseg {
    	struct msg_msgseg *next;
    	/* the next part of the message follows immediately */
    };
    
    #define DATALEN_MSG	((size_t)PAGE_SIZE-sizeof(struct msg_msg))
    #define DATALEN_SEG	((size_t)PAGE_SIZE-sizeof(struct msg_msgseg))
    
    
    static struct msg_msg *alloc_msg(size_t len)
    {
    	struct msg_msg *msg;
    	struct msg_msgseg **pseg;
    	size_t alen;
    
    	alen = min(len, DATALEN_MSG);
    	msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL_ACCOUNT);
    	if (msg == NULL)
    		return NULL;
    
    	msg->next = NULL;
    	msg->security = NULL;
    
    	len -= alen;
    	pseg = &msg->next;
    	while (len > 0) {
    		struct msg_msgseg *seg;
    
    		cond_resched();
    
    		alen = min(len, DATALEN_SEG);
    		seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL_ACCOUNT);
    		if (seg == NULL)
    			goto out_err;
    		*pseg = seg;
    		seg->next = NULL;
    		pseg = &seg->next;
    		len -= alen;
    	}
    
    	return msg;
    
    out_err:
    	free_msg(msg);
    	return NULL;
    }
    
    struct msg_msg *load_msg(const void __user *src, size_t len)
    {
    	struct msg_msg *msg;
    	struct msg_msgseg *seg;
    	int err = -EFAULT;
    	size_t alen;
    
    	msg = alloc_msg(len);
    	if (msg == NULL)
    		return ERR_PTR(-ENOMEM);
    
    	alen = min(len, DATALEN_MSG);
    	if (copy_from_user(msg + 1, src, alen))
    		goto out_err;
    
    	for (seg = msg->next; seg != NULL; seg = seg->next) {
    		len -= alen;
    		src = (char __user *)src + alen;
    		alen = min(len, DATALEN_SEG);
    		if (copy_from_user(seg + 1, src, alen))
    			goto out_err;
    	}
    
    	err = security_msg_msg_alloc(msg);
    	if (err)
    		goto out_err;
    
    	return msg;
    
    out_err:
    	free_msg(msg);
    	return ERR_PTR(err);
    }
    #ifdef CONFIG_CHECKPOINT_RESTORE
    struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
    {
    	struct msg_msgseg *dst_pseg, *src_pseg;
    	size_t len = src->m_ts;
    	size_t alen;
    
    	if (src->m_ts > dst->m_ts)
    		return ERR_PTR(-EINVAL);
    
    	alen = min(len, DATALEN_MSG);
    	memcpy(dst + 1, src + 1, alen);
    
    	for (dst_pseg = dst->next, src_pseg = src->next;
    	     src_pseg != NULL;
    	     dst_pseg = dst_pseg->next, src_pseg = src_pseg->next) {
    
    		len -= alen;
    		alen = min(len, DATALEN_SEG);
    		memcpy(dst_pseg + 1, src_pseg + 1, alen);
    	}
    
    	dst->m_type = src->m_type;
    	dst->m_ts = src->m_ts;
    
    	return dst;
    }
    #else
    struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
    {
    	return ERR_PTR(-ENOSYS);
    }
    #endif
    int store_msg(void __user *dest, struct msg_msg *msg, size_t len)
    {
    	size_t alen;
    	struct msg_msgseg *seg;
    
    	alen = min(len, DATALEN_MSG);
    	if (copy_to_user(dest, msg + 1, alen))
    		return -1;
    
    	for (seg = msg->next; seg != NULL; seg = seg->next) {
    		len -= alen;
    		dest = (char __user *)dest + alen;
    		alen = min(len, DATALEN_SEG);
    		if (copy_to_user(dest, seg + 1, alen))
    			return -1;
    	}
    	return 0;
    }
    
    void free_msg(struct msg_msg *msg)
    {
    	struct msg_msgseg *seg;
    
    	security_msg_msg_free(msg);
    
    	seg = msg->next;
    	kfree(msg);
    	while (seg != NULL) {
    		struct msg_msgseg *tmp = seg->next;
    
    		cond_resched();
    		kfree(seg);
    		seg = tmp;
    	}
    }
    

      

  • 相关阅读:
    C# 使用EWS 读取 Exchange 未读邮件并设置为已读
    .NET 操作 Exchange示例
    Elsa-Core 工作流 使用代码启动审批流或触发审批任务
    Elsa-Core-workflow 从代码启动指定工作流
    .NET CORE 开源工作流 elsa-core 基础使用示例
    文档翻译经验分享(Markdown)
    Orchard Core 开发示例教程
    VMware 与 Hyper-v 并存, 可同时运行 非启动项
    SmtpException: Failure sending mail. ---> System.InvalidOperationException: Asynchronous operations are not allowed in this context.
    Linux (Deppin ,Ubuntu )开发环境配置,VUE & dotnetcore 解决 yarn 找不到问题
  • 原文地址:https://www.cnblogs.com/still-smile/p/12040582.html
Copyright © 2011-2022 走看看