ipc技术linux c,linux IPC util.c分析

size;i++)

ids->entries[i].p = NULL;

}

/**

*    在ipc标识集中查找键值为key的ipc标识

*

*    Returns the identifier if found or -1 if not.

*/

int ipc_findkey(struct ipc_ids* ids, key_t key)

{

int id;

struct kern_ipc_perm* p;

for (id = 0; id <= ids->max_id; id++) {

p = ids->entries[id].p;

if(p==NULL)

continue;

if (key == p->key)

return id;

}

return -1;

}

static int grow_ary(struct ipc_ids* ids, int newsize)

{

struct ipc_id* new;

struct ipc_id* old;

int i;

//限定newsize大小不超过IPCMNI

if(newsize > IPCMNI)

newsize = IPCMNI;

if(newsize <= ids->size)

return newsize;

//分配newsize大小的struct ipc_id空间

new = ipc_alloc(sizeof(struct ipc_id)*newsize);

if(new == NULL)

return ids->size;

memcpy(new, ids->entries, sizeof(struct ipc_id)*ids->size);

for(i=ids->size;inew[i].p = NULL;

}

spin_lock(&ids->ary);

old = ids->entries;

ids->entries = new;

i = ids->size;

ids->size = newsize;

spin_unlock(&ids->ary);

//回收原先分配的struct ipc_id空间

ipc_free(old, sizeof(struct ipc_id)*i);

return ids->size;

}

/**

在ipc标识集中添加一个新标识符

*

*    Add an entry 'new' to the IPC arrays. The permissions object is

*    initialised and the first free entry is set up and the id assigned

*    is returned. The list is returned in a locked state on success.

*    On failure the list is not locked and -1 is returned.

*/

int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)

{

int id;

size = grow_ary(ids,size);

//依次查找,直到发现第一个非空项

for (id = 0; id < size; id++) {

if(ids->entries[id].p == NULL)

goto found;

}

return -1;

found:

ids->in_use++;

if (id > ids->max_id)

ids->max_id = id;

new->cuid = new->uid = current->euid;

new->gid = new->cgid = current->egid;

new->seq = ids->seq++;

if(ids->seq > ids->seq_max)

ids->seq = 0;

spin_lock(&ids->ary);

ids->entries[id].p = new;

return id;

}

/**

从ipc标识集中删除一个标识符

*    The identifier must be valid, and in use. The kernel will panic if

*    fed an invalid identifier. The entry is removed and internal

*    variables recomputed. The object associated with the identifier

*    is returned.

*/

struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)

{

struct kern_ipc_perm* p;

int lid = id % SEQ_MULTIPLIER;

if(lid >= ids->size)

BUG();

p = ids->entries[lid].p;

ids->entries[lid].p = NULL;

if(p==NULL)

BUG();

ids->in_use--;

if (lid == ids->max_id) {

do {

lid--;

if(lid == -1)

break;

} while (ids->entries[lid].p == NULL);

ids->max_id = lid;

}

return p;

}

/**

分配size大小的空间

*    Allocate memory from the appropriate pools and return a pointer to it.

*    NULL is returned if the allocation fails

*/

void* ipc_alloc(int size)

{

void* out;

if(size > PAGE_SIZE)

out = vmalloc(size);

else

out = kmalloc(size, GFP_KERNEL);

return out;

}

/**

释放ptr指向的空间

*

*    Free a block created with ipc_alloc. The caller must know the size

*    used in the allocation call.

*/

void ipc_free(void* ptr, int size)

{

if(size > PAGE_SIZE)

vfree(ptr);

else

kfree(ptr);

}

/**

查看ipc访问权限

*    Check user, group, other permissions for access

*    to ipc resources. return 0 if allowed

*/

int ipcperms (struct kern_ipc_perm *ipcp, short flag)

{    /* flag will most probably be 0 or S_...UGO from */

int requested_mode, granted_mode;

requested_mode = (flag >> 6) | (flag >> 3) | flag;

granted_mode = ipcp->mode;

if (current->euid == ipcp->cuid || current->euid == ipcp->uid)

granted_mode >>= 6;

else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))

granted_mode >>= 3;

/* is there some bit set in requested_mode but not in granted_mode? */

if ((requested_mode & ~granted_mode & 0007) &&

!capable(CAP_IPC_OWNER))

return -1;

return 0;

}

/**

转换struct kern_ipc_perm数据到用户空间

*

*    Turn the kernel object 'in' into a set of permissions descriptions

*    for returning to userspace (out).

*/

void kernel_to_ipc64_perm (struct kern_ipc_perm *in, struct ipc64_perm *out)

{

out->key    = in->key;

out->uid    = in->uid;

out->gid    = in->gid;

out->cuid    = in->cuid;

out->cgid    = in->cgid;

out->mode    = in->mode;

out->seq    = in->seq;

}

/**

转换struct ipc64_perm数据到struct ipc_perm

*    Turn the new style permissions object in into a compatibility

*    object and store it into the 'out' pointer.

*/

void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out)

{

out->key    = in->key;

out->uid    = NEW_TO_OLD_UID(in->uid);

out->gid    = NEW_TO_OLD_GID(in->gid);

out->cuid    = NEW_TO_OLD_UID(in->cuid);

out->cgid    = NEW_TO_OLD_GID(in->cgid);

out->mode    = in->mode;

out->seq    = in->seq;

}

#endif /* CONFIG_SYSVIPC */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值