欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
3--共享內存的實(shí)踐到內核--撤銷(xiāo)共享內存的映射和控制 - 如何從應用程序進(jìn)入linux內...
我們還是先從應用界面看起,如果沒(méi)有看過(guò)我們的實(shí)踐程序的朋友請看這里
shmdt(shared_memory) == -1這句代碼是撤銷(xiāo)共享內存,另一句shmctl(shmid, IPC_RMID, 0) == -1是刪除共享內存。我們還是按照原來(lái)的分析方法這里不再重復如何進(jìn)入sys_ipc()的,我們把進(jìn)入sys_ipc()后的代碼重要的代碼貼出來(lái)

    case SHMDT:
        return sys_shmdt ((char __user *)ptr);
。。。。。。省略
    case SHMCTL:
        return sys_shmctl (first, second,
                 (struct shmid_ds __user *) ptr);

也就是看到應用程序與我們內核的系統調用函數參數是對正的,參數的含義我們就不用再重復介紹了,我們分別看一下sys_shmdt()函數和sys_shmctl()函數。

asmlinkage long sys_shmdt(char __user *shmaddr)
{
    struct mm_struct *mm = current->mm;
    struct vm_area_struct *vma, *next;
    unsigned long addr = (unsigned long)shmaddr;
    loff_t size = 0;
    int retval = -EINVAL;

    if (addr & ~PAGE_MASK)
        return retval;

    down_write(&mm->mmap_sem);

    /*
     * This function tries to be smart and unmap shm segments that
     * were modified by partial mlock or munmap calls:
     * - It first determines the size of the shm segment that should be
     * unmapped: It searches for a vma that is backed by shm and that
     * started at address shmaddr. It records it's size and then unmaps
     * it.
     * - Then it unmaps all shm vmas that started at shmaddr and that
     * are within the initially determined size.
     * Errors from do_munmap are ignored: the function only fails if
     * it's called with invalid parameters or if it's called to unmap
     * a part of a vma. Both calls in this function are for full vmas,
     * the parameters are directly copied from the vma itself and always
     * valid - therefore do_munmap cannot fail. (famous last words?)
     */

    /*
     * If it had been mremap()'d, the starting address would not
     * match the usual checks anyway. So assume all vma's are
     * above the starting address given.
     */

    vma = find_vma(mm, addr);

    while (vma) {
        next = vma->vm_next;

        /*
         * Check if the starting address would match, i.e. it's
         * a fragment created by mprotect() and/or munmap(), or it
         * otherwise it starts at this address with no hassles.
         */

        if ((vma->vm_ops == &shm_vm_ops) &&
            (vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) {


            size = vma->vm_file->f_path.dentry->d_inode->i_size;
            do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
            /*
             * We discovered the size of the shm segment, so
             * break out of here and fall through to the next
             * loop that uses the size information to stop
             * searching for matching vma's.
             */

            retval = 0;
            vma = next;
            break;
        }
        vma = next;
    }

    /*
     * We need look no further than the maximum address a fragment
     * could possibly have landed at. Also cast things to loff_t to
     * prevent overflows and make comparisions vs. equal-width types.
     */

    size = PAGE_ALIGN(size);
    while (vma && (loff_t)(vma->vm_end - addr) <= size) {
        next = vma->vm_next;

        /* finding a matching vma now does not alter retval */
        if ((vma->vm_ops == &shm_vm_ops) &&
            (vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff)

            do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
        vma = next;
    }

    up_write(&mm->mmap_sem);
    return retval;
}

其實(shí)這段代碼并不復雜,主要是注釋多有點(diǎn)嚇人,呵呵,如果有內核基礎的朋友相信不難理解這段代碼,但是對于其他朋友我們要說(shuō)明一點(diǎn),vma結構變量是表示虛擬空間的專(zhuān)用數據結構,這段代碼首先是找到共享內存在進(jìn)程中指定地址處的虛擬空間段,然后利用do_munmap()函數撤銷(xiāo)對這個(gè)虛擬空間段的所有內存映射。do_munmap()函數我們還是在內存管理那部分分析吧,這里朋友們先暫且知道有這個(gè)一個(gè)函數,從函數名稱(chēng)上也能理解出他的作用。

我們再看另一個(gè)控制共享內存的函數sys_shmctl()

asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
{
    struct shmid_kernel *shp;
    int err, version;
    struct ipc_namespace *ns;

    if (cmd < 0 || shmid < 0) {
        err = -EINVAL;
        goto out;
    }

    version = ipc_parse_version(&cmd);
    ns = current->nsproxy->ipc_ns;

    switch (cmd) { /* replace with proc interface ? */
    case IPC_INFO:
    {
        struct shminfo64 shminfo;

        err = security_shm_shmctl(NULL, cmd);
        if (err)
            return err;

        memset(&shminfo,0,sizeof(shminfo));
        shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
        shminfo.shmmax = ns->shm_ctlmax;
        shminfo.shmall = ns->shm_ctlall;

        shminfo.shmmin = SHMMIN;
        if(copy_shminfo_to_user (buf, &shminfo, version))
            return -EFAULT;

        down_read(&shm_ids(ns).rw_mutex);
        err = ipc_get_maxid(&shm_ids(ns));
        up_read(&shm_ids(ns).rw_mutex);

        if(err<0)
            err = 0;
        goto out;
    }
    case SHM_INFO:
    {
        struct shm_info shm_info;

        err = security_shm_shmctl(NULL, cmd);
        if (err)
            return err;

        memset(&shm_info,0,sizeof(shm_info));
        down_read(&shm_ids(ns).rw_mutex);
        shm_info.used_ids = shm_ids(ns).in_use;
        shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp);
        shm_info.shm_tot = ns->shm_tot;
        shm_info.swap_attempts = 0;
        shm_info.swap_successes = 0;
        err = ipc_get_maxid(&shm_ids(ns));
        up_read(&shm_ids(ns).rw_mutex);
        if(copy_to_user (buf, &shm_info, sizeof(shm_info))) {
            err = -EFAULT;
            goto out;
        }

        err = err < 0 ? 0 : err;
        goto out;
    }
    case SHM_STAT:
    case IPC_STAT:
    {
        struct shmid64_ds tbuf;
        int result;

        if (!buf) {
            err = -EFAULT;
            goto out;
        }

        if (cmd == SHM_STAT) {
            shp = shm_lock(ns, shmid);
            if (IS_ERR(shp)) {
                err = PTR_ERR(shp);
                goto out;
            }
            result = shp->shm_perm.id;
        } else {
            shp = shm_lock_check(ns, shmid);
            if (IS_ERR(shp)) {
                err = PTR_ERR(shp);
                goto out;
            }
            result = 0;
        }
        err=-EACCES;
        if (ipcperms (&shp->shm_perm, S_IRUGO))
            goto out_unlock;
        err = security_shm_shmctl(shp, cmd);
        if (err)
            goto out_unlock;
        memset(&tbuf, 0, sizeof(tbuf));
        kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);
        tbuf.shm_segsz    = shp->shm_segsz;
        tbuf.shm_atime    = shp->shm_atim;
        tbuf.shm_dtime    = shp->shm_dtim;
        tbuf.shm_ctime    = shp->shm_ctim;
        tbuf.shm_cpid    = shp->shm_cprid;
        tbuf.shm_lpid    = shp->shm_lprid;
        tbuf.shm_nattch    = shp->shm_nattch;
        shm_unlock(shp);
        if(copy_shmid_to_user (buf, &tbuf, version))
            err = -EFAULT;
        else
            err = result;
        goto out;
    }
    case SHM_LOCK:
    case SHM_UNLOCK:
    {
        shp = shm_lock_check(ns, shmid);
        if (IS_ERR(shp)) {
            err = PTR_ERR(shp);
            goto out;
        }

        err = audit_ipc_obj(&(shp->shm_perm));
        if (err)
            goto out_unlock;

        if (!capable(CAP_IPC_LOCK)) {
            err = -EPERM;
            if (current->euid != shp->shm_perm.uid &&
             current->euid != shp->shm_perm.cuid)
                goto out_unlock;
            if (cmd == SHM_LOCK &&
             !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
                goto out_unlock;
        }

        err = security_shm_shmctl(shp, cmd);
        if (err)
            goto out_unlock;
        
        if(cmd==SHM_LOCK) {
            struct user_struct * user = current->user;
            if (!is_file_hugepages(shp->shm_file)) {
                err = shmem_lock(shp->shm_file, 1, user);
                if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){
                    shp->shm_perm.mode |= SHM_LOCKED;
                    shp->mlock_user = user;
                }
            }
        } else if (!is_file_hugepages(shp->shm_file)) {
            shmem_lock(shp->shm_file, 0, shp->mlock_user);
            shp->shm_perm.mode &= ~SHM_LOCKED;
            shp->mlock_user = NULL;
        }
        shm_unlock(shp);
        goto out;
    }
    case IPC_RMID:
    case IPC_SET:
        err = shmctl_down(ns, shmid, cmd, buf, version);
        return err;
    default:
        return -EINVAL;
    }

out_unlock:
    shm_unlock(shp);
out:
    return err;
}

這段代碼盡管長(cháng),我們也不用全部看,有興趣可以認真研究,我們說(shuō)過(guò)是從應用程序來(lái)順藤摸瓜的,這里就到了代碼中最下面的紅色部分即IPC_RMID,我們看到他調用了另一個(gè)函數shmctl_down()

static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
         struct shmid_ds __user *buf, int version)
{
    struct kern_ipc_perm *ipcp;
    struct shmid64_ds shmid64;
    struct shmid_kernel *shp;
    int err;

    if (cmd == IPC_SET) {
        if (copy_shmid_from_user(&shmid64, buf, version))
            return -EFAULT;
    }

    ipcp = ipcctl_pre_down(&shm_ids(ns), shmid, cmd, &shmid64.shm_perm, 0);
    if (IS_ERR(ipcp))
        return PTR_ERR(ipcp);

    shp = container_of(ipcp, struct shmid_kernel, shm_perm);

    err = security_shm_shmctl(shp, cmd);
    if (err)
        goto out_unlock;
    switch (cmd) {
    case IPC_RMID:
        do_shm_rmid(ns, ipcp);

        goto out_up;
    case IPC_SET:
        ipc_update_perm(&shmid64.shm_perm, ipcp);
        shp->shm_ctim = get_seconds();
        break;
    default:
        err = -EINVAL;
    }
out_unlock:
    shm_unlock(shp);
out_up:
    up_write(&shm_ids(ns).rw_mutex);
    return err;
}

在上面的代碼中將會(huì )執行重要的函數do_shm_rmid()

static void do_shm_rmid(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
{
    struct shmid_kernel *shp;
    shp = container_of(ipcp, struct shmid_kernel, shm_perm);

    if (shp->shm_nattch){
        shp->shm_perm.mode |= SHM_DEST;
        /* Do not find it any more */
        shp->shm_perm.key = IPC_PRIVATE;
        shm_unlock(shp);
    } else
        shm_destroy(ns, shp);
}

很明顯這個(gè)數據結構根據ipc機制找到我們以前分配的共享內存的結構struct shmid_kernel *shp,銷(xiāo)毀他并釋放了所占用的內核空間。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Linux環(huán)境進(jìn)程間通信(五): 共享內存(下)
Linux進(jìn)程通信 共享內存+信號量
進(jìn)程間通信之共享內存
linux進(jìn)程間共享內存通信詳解
Linux環(huán)境進(jìn)程間通信(五): 共享內存(下)-Linux -華夏名網(wǎng)資訊中心 虛擬主機...
共享內存
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久