1 use crate::{
2 arch::mm::LockedFrameAllocator,
3 filesystem::vfs::syscall::ModeType,
4 libs::{
5 align::page_align_up,
6 spinlock::{SpinLock, SpinLockGuard},
7 },
8 mm::{
9 allocator::page_frame::{FrameAllocator, PageFrameCount, PhysPageFrame},
10 page::{page_manager_lock_irqsave, Page},
11 PhysAddr,
12 },
13 process::{Pid, ProcessManager},
14 syscall::user_access::{UserBufferReader, UserBufferWriter},
15 time::PosixTimeSpec,
16 };
17 use alloc::{sync::Arc, vec::Vec};
18 use core::sync::atomic::{compiler_fence, Ordering};
19 use hashbrown::{HashMap, HashSet};
20 use ida::IdAllocator;
21 use log::info;
22 use num::ToPrimitive;
23 use system_error::SystemError;
24
25 pub static mut SHM_MANAGER: Option<SpinLock<ShmManager>> = None;
26
27 /// 用于创建新的私有IPC对象
28 pub const IPC_PRIVATE: ShmKey = ShmKey::new(0);
29
30 /// 初始化SHM_MANAGER
shm_manager_init()31 pub fn shm_manager_init() {
32 info!("shm_manager_init");
33 let shm_manager = SpinLock::new(ShmManager::new());
34
35 compiler_fence(Ordering::SeqCst);
36 unsafe { SHM_MANAGER = Some(shm_manager) };
37 compiler_fence(Ordering::SeqCst);
38
39 info!("shm_manager_init done");
40 }
41
shm_manager_lock() -> SpinLockGuard<'static, ShmManager>42 pub fn shm_manager_lock() -> SpinLockGuard<'static, ShmManager> {
43 unsafe { SHM_MANAGER.as_ref().unwrap().lock() }
44 }
45
46 int_like!(ShmId, usize);
47 int_like!(ShmKey, usize);
48
49 bitflags! {
50 pub struct ShmFlags:u32{
51 const SHM_RDONLY = 0o10000;
52 const SHM_RND = 0o20000;
53 const SHM_REMAP = 0o40000;
54 const SHM_EXEC = 0o100000;
55 const SHM_HUGETLB = 0o4000;
56
57 const IPC_CREAT = 0o1000;
58 const IPC_EXCL = 0o2000;
59
60 const SHM_DEST = 0o1000;
61 const SHM_LOCKED = 0o2000;
62 }
63 }
64
65 /// 管理共享内存段信息的操作码
66 #[derive(Eq, Clone, Copy)]
67 pub enum ShmCtlCmd {
68 /// 删除共享内存段
69 IpcRmid = 0,
70 /// 设置KernIpcPerm选项
71 IpcSet = 1,
72 /// 获取ShmIdDs
73 IpcStat = 2,
74 /// 查看ShmMetaData
75 IpcInfo = 3,
76
77 /// 不允许共享内存段被置换出物理内存
78 ShmLock = 11,
79 /// 允许共享内存段被置换出物理内存
80 ShmUnlock = 12,
81 /// 查看ShmMetaData
82 ShmStat = 13,
83 /// 查看ShmInfo
84 ShmInfo = 14,
85 /// 查看ShmMetaData
86 ShmtStatAny = 15,
87
88 Default,
89 }
90
91 impl From<usize> for ShmCtlCmd {
from(cmd: usize) -> ShmCtlCmd92 fn from(cmd: usize) -> ShmCtlCmd {
93 match cmd {
94 0 => Self::IpcRmid,
95 1 => Self::IpcSet,
96 2 => Self::IpcStat,
97 3 => Self::IpcInfo,
98 11 => Self::ShmLock,
99 12 => Self::ShmUnlock,
100 13 => Self::ShmStat,
101 14 => Self::ShmInfo,
102 15 => Self::ShmtStatAny,
103 _ => Self::Default,
104 }
105 }
106 }
107
108 impl PartialEq for ShmCtlCmd {
eq(&self, other: &ShmCtlCmd) -> bool109 fn eq(&self, other: &ShmCtlCmd) -> bool {
110 *self as usize == *other as usize
111 }
112 }
113
114 /// 共享内存管理器
115 #[derive(Debug)]
116 pub struct ShmManager {
117 /// ShmId分配器
118 id_allocator: IdAllocator,
119 /// ShmId映射共享内存信息表
120 id2shm: HashMap<ShmId, KernelShm>,
121 /// ShmKey映射ShmId表
122 key2id: HashMap<ShmKey, ShmId>,
123 }
124
125 impl ShmManager {
new() -> Self126 pub fn new() -> Self {
127 ShmManager {
128 id_allocator: IdAllocator::new(0, usize::MAX - 1).unwrap(),
129 id2shm: HashMap::new(),
130 key2id: HashMap::new(),
131 }
132 }
133
134 /// # 添加共享内存段
135 ///
136 /// ## 参数
137 ///
138 /// - `key`: 共享内存键值
139 /// - `size`: 共享内存大小
140 /// - `shmflg`: 共享内存标志
141 ///
142 /// ## 返回值
143 ///
144 /// 成功:共享内存id
145 /// 失败:对应错误码
add( &mut self, key: ShmKey, size: usize, shmflg: ShmFlags, ) -> Result<usize, SystemError>146 pub fn add(
147 &mut self,
148 key: ShmKey,
149 size: usize,
150 shmflg: ShmFlags,
151 ) -> Result<usize, SystemError> {
152 // 判断共享内存大小是否过小或溢出
153 if !(PosixShmMetaInfo::SHMMIN..=PosixShmMetaInfo::SHMMAX).contains(&size) {
154 return Err(SystemError::EINVAL);
155 }
156
157 let id = self.id_allocator.alloc().expect("No more id to allocate.");
158 let shm_id = ShmId::new(id);
159
160 // 分配共享内存页面
161 let page_count = PageFrameCount::from_bytes(page_align_up(size)).unwrap();
162 let phys_page =
163 unsafe { LockedFrameAllocator.allocate(page_count) }.ok_or(SystemError::EINVAL)?;
164 // 创建共享内存page,并添加到PAGE_MANAGER中
165 let mut page_manager_guard = page_manager_lock_irqsave();
166 let mut cur_phys = PhysPageFrame::new(phys_page.0);
167 for _ in 0..page_count.data() {
168 let page = Arc::new(Page::new(true, cur_phys.phys_address()));
169 page.write_irqsave().set_shm_id(shm_id);
170 let paddr = cur_phys.phys_address();
171 page_manager_guard.insert(paddr, &page);
172 cur_phys = cur_phys.next();
173 }
174
175 // 创建共享内存信息结构体
176 let paddr = phys_page.0;
177 let kern_ipc_perm = KernIpcPerm {
178 id: shm_id,
179 key,
180 uid: 0,
181 gid: 0,
182 _cuid: 0,
183 _cgid: 0,
184 mode: shmflg & ShmFlags::from_bits_truncate(ModeType::S_IRWXUGO.bits()),
185 _seq: 0,
186 };
187 let shm_kernel = KernelShm::new(kern_ipc_perm, paddr, size);
188
189 // 将key、id及其对应KernelShm添加到表中
190 self.id2shm.insert(shm_id, shm_kernel);
191 self.key2id.insert(key, shm_id);
192
193 return Ok(shm_id.data());
194 }
195
contains_key(&self, key: &ShmKey) -> Option<&ShmId>196 pub fn contains_key(&self, key: &ShmKey) -> Option<&ShmId> {
197 self.key2id.get(key)
198 }
199
get_mut(&mut self, id: &ShmId) -> Option<&mut KernelShm>200 pub fn get_mut(&mut self, id: &ShmId) -> Option<&mut KernelShm> {
201 self.id2shm.get_mut(id)
202 }
203
free_key(&mut self, key: &ShmKey)204 pub fn free_key(&mut self, key: &ShmKey) {
205 self.key2id.remove(key);
206 }
207
free_id(&mut self, id: &ShmId)208 pub fn free_id(&mut self, id: &ShmId) {
209 self.id2shm.remove(id);
210 self.id_allocator.free(id.0);
211 }
212
ipc_info(&self, user_buf: *const u8, from_user: bool) -> Result<usize, SystemError>213 pub fn ipc_info(&self, user_buf: *const u8, from_user: bool) -> Result<usize, SystemError> {
214 let mut user_buffer_writer = UserBufferWriter::new(
215 user_buf as *mut u8,
216 core::mem::size_of::<PosixShmMetaInfo>(),
217 from_user,
218 )?;
219
220 let shm_meta_info = PosixShmMetaInfo::new();
221 user_buffer_writer.copy_one_to_user(&shm_meta_info, 0)?;
222
223 return Ok(0);
224 }
225
shm_info(&self, user_buf: *const u8, from_user: bool) -> Result<usize, SystemError>226 pub fn shm_info(&self, user_buf: *const u8, from_user: bool) -> Result<usize, SystemError> {
227 // 已使用id数量
228 let used_ids = self.id2shm.len().to_i32().unwrap();
229 // 共享内存总和
230 let shm_tot = self.id2shm.iter().fold(0, |acc, (_, kernel_shm)| {
231 acc + PageFrameCount::from_bytes(page_align_up(kernel_shm.shm_size))
232 .unwrap()
233 .data()
234 });
235 let shm_info = PosixShmInfo::new(used_ids, shm_tot, 0, 0, 0, 0);
236
237 let mut user_buffer_writer = UserBufferWriter::new(
238 user_buf as *mut u8,
239 core::mem::size_of::<PosixShmInfo>(),
240 from_user,
241 )?;
242 user_buffer_writer.copy_one_to_user(&shm_info, 0)?;
243
244 return Ok(0);
245 }
246
shm_stat( &self, id: ShmId, cmd: ShmCtlCmd, user_buf: *const u8, from_user: bool, ) -> Result<usize, SystemError>247 pub fn shm_stat(
248 &self,
249 id: ShmId,
250 cmd: ShmCtlCmd,
251 user_buf: *const u8,
252 from_user: bool,
253 ) -> Result<usize, SystemError> {
254 let kernel_shm = self.id2shm.get(&id).ok_or(SystemError::EINVAL)?;
255 let key = kernel_shm.kern_ipc_perm.key.data().to_i32().unwrap();
256 let mode = kernel_shm.kern_ipc_perm.mode.bits();
257
258 let shm_perm = PosixIpcPerm::new(key, 0, 0, 0, 0, mode);
259 let shm_segsz = kernel_shm.shm_size;
260 let shm_atime = kernel_shm.shm_atim.total_nanos();
261 let shm_dtime = kernel_shm.shm_dtim.total_nanos();
262 let shm_ctime = kernel_shm.shm_ctim.total_nanos();
263 let shm_cpid = kernel_shm.shm_cprid.data().to_u32().unwrap();
264 let shm_lpid = kernel_shm.shm_lprid.data().to_u32().unwrap();
265 let shm_map_count = kernel_shm.map_count();
266 let shm_id_ds = PosixShmIdDs {
267 shm_perm,
268 shm_segsz,
269 shm_atime,
270 shm_dtime,
271 shm_ctime,
272 shm_cpid,
273 shm_lpid,
274 shm_map_count,
275 _unused1: 0,
276 _unused2: 0,
277 };
278
279 let mut user_buffer_writer = UserBufferWriter::new(
280 user_buf as *mut u8,
281 core::mem::size_of::<PosixShmIdDs>(),
282 from_user,
283 )?;
284 user_buffer_writer.copy_one_to_user(&shm_id_ds, 0)?;
285
286 let r: usize = if cmd == ShmCtlCmd::IpcStat {
287 0
288 } else {
289 id.data()
290 };
291
292 return Ok(r);
293 }
294
ipc_set( &mut self, id: ShmId, user_buf: *const u8, from_user: bool, ) -> Result<usize, SystemError>295 pub fn ipc_set(
296 &mut self,
297 id: ShmId,
298 user_buf: *const u8,
299 from_user: bool,
300 ) -> Result<usize, SystemError> {
301 let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
302
303 let user_buffer_reader =
304 UserBufferReader::new(user_buf, core::mem::size_of::<PosixShmIdDs>(), from_user)?;
305 let mut shm_id_ds = PosixShmIdDs::default();
306 user_buffer_reader.copy_one_from_user(&mut shm_id_ds, 0)?;
307
308 kernel_shm.copy_from(shm_id_ds);
309
310 return Ok(0);
311 }
312
ipc_rmid(&mut self, id: ShmId) -> Result<usize, SystemError>313 pub fn ipc_rmid(&mut self, id: ShmId) -> Result<usize, SystemError> {
314 let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
315 kernel_shm.set_mode(ShmFlags::SHM_DEST, true);
316
317 let mut cur_phys = PhysPageFrame::new(kernel_shm.shm_start_paddr);
318 let count = PageFrameCount::from_bytes(page_align_up(kernel_shm.shm_size)).unwrap();
319 let key = kernel_shm.kern_ipc_perm.key;
320 let id = kernel_shm.kern_ipc_perm.id;
321 let map_count = kernel_shm.map_count();
322
323 let mut page_manager_guard = page_manager_lock_irqsave();
324 if map_count > 0 {
325 // 设置共享内存物理页当映射计数等于0时可被回收
326 for _ in 0..count.data() {
327 let page = page_manager_guard.get_unwrap(&cur_phys.phys_address());
328 page.write_irqsave().set_dealloc_when_zero(true);
329
330 cur_phys = cur_phys.next();
331 }
332
333 // 释放key,不让后续进程连接
334 self.free_key(&key);
335 } else {
336 // 释放共享内存物理页
337 for _ in 0..count.data() {
338 let paddr = cur_phys.phys_address();
339 unsafe {
340 LockedFrameAllocator.free(paddr, PageFrameCount::new(1));
341 }
342 // 将已回收的物理页面对应的Page从PAGE_MANAGER中删去
343 page_manager_guard.remove_page(&paddr);
344 cur_phys = cur_phys.next();
345 }
346
347 // 释放key和id
348 self.free_id(&id);
349 self.free_key(&key)
350 }
351
352 return Ok(0);
353 }
354
shm_lock(&mut self, id: ShmId) -> Result<usize, SystemError>355 pub fn shm_lock(&mut self, id: ShmId) -> Result<usize, SystemError> {
356 let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
357 kernel_shm.set_mode(ShmFlags::SHM_LOCKED, true);
358
359 return Ok(0);
360 }
361
shm_unlock(&mut self, id: ShmId) -> Result<usize, SystemError>362 pub fn shm_unlock(&mut self, id: ShmId) -> Result<usize, SystemError> {
363 let kernel_shm = self.id2shm.get_mut(&id).ok_or(SystemError::EINVAL)?;
364 kernel_shm.set_mode(ShmFlags::SHM_LOCKED, false);
365
366 return Ok(0);
367 }
368 }
369 /// 共享内存信息
370 #[derive(Debug)]
371 pub struct KernelShm {
372 /// 权限信息
373 kern_ipc_perm: KernIpcPerm,
374 /// 共享内存起始物理地址
375 shm_start_paddr: PhysAddr,
376 /// 共享内存大小(bytes),注意是用户指定的大小(未经过页面对齐)
377 shm_size: usize,
378 /// 最后一次连接的时间
379 shm_atim: PosixTimeSpec,
380 /// 最后一次断开连接的时间
381 shm_dtim: PosixTimeSpec,
382 /// 最后一次更改信息的时间
383 shm_ctim: PosixTimeSpec,
384 /// 创建者进程id
385 shm_cprid: Pid,
386 /// 最后操作者进程id
387 shm_lprid: Pid,
388 }
389
390 impl KernelShm {
new(kern_ipc_perm: KernIpcPerm, shm_start_paddr: PhysAddr, shm_size: usize) -> Self391 pub fn new(kern_ipc_perm: KernIpcPerm, shm_start_paddr: PhysAddr, shm_size: usize) -> Self {
392 let shm_cprid = ProcessManager::current_pid();
393 KernelShm {
394 kern_ipc_perm,
395 shm_start_paddr,
396 shm_size,
397 shm_atim: PosixTimeSpec::new(0, 0),
398 shm_dtim: PosixTimeSpec::new(0, 0),
399 shm_ctim: PosixTimeSpec::now(),
400 shm_cprid,
401 shm_lprid: shm_cprid,
402 }
403 }
404
start_paddr(&self) -> PhysAddr405 pub fn start_paddr(&self) -> PhysAddr {
406 self.shm_start_paddr
407 }
408
size(&self) -> usize409 pub fn size(&self) -> usize {
410 self.shm_size
411 }
412
413 /// 更新最后连接时间
update_atim(&mut self)414 pub fn update_atim(&mut self) {
415 // 更新最后一次连接时间
416 self.shm_atim = PosixTimeSpec::now();
417
418 // 更新最后操作当前共享内存的进程ID
419 self.shm_lprid = ProcessManager::current_pid();
420 }
421
422 /// 更新最后断开连接时间
update_dtim(&mut self)423 pub fn update_dtim(&mut self) {
424 // 更新最后一次断开连接时间
425 self.shm_dtim = PosixTimeSpec::now();
426
427 // 更新最后操作当前共享内存的进程ID
428 self.shm_lprid = ProcessManager::current_pid();
429 }
430
431 /// 更新最后一次修改信息的时间
update_ctim(&mut self)432 pub fn update_ctim(&mut self) {
433 // 更新最后一次修改信息的时间
434 self.shm_ctim = PosixTimeSpec::now();
435 }
436
437 /// 共享内存段的映射计数(有多少个不同的VMA映射)
map_count(&self) -> usize438 pub fn map_count(&self) -> usize {
439 let mut page_manager_guard = page_manager_lock_irqsave();
440 let mut id_set: HashSet<usize> = HashSet::new();
441 let mut cur_phys = PhysPageFrame::new(self.shm_start_paddr);
442 let page_count = PageFrameCount::from_bytes(page_align_up(self.shm_size)).unwrap();
443
444 for _ in 0..page_count.data() {
445 let page = page_manager_guard.get(&cur_phys.phys_address()).unwrap();
446 id_set.extend(
447 page.read_irqsave()
448 .anon_vma()
449 .iter()
450 .map(|vma| vma.id())
451 .collect::<Vec<_>>(),
452 );
453
454 cur_phys = cur_phys.next();
455 }
456
457 // 由于LockedVMA的id是独一无二的,因此有多少个不同的id,就代表着有多少个不同的VMA映射到共享内存段
458 return id_set.len();
459 }
460
copy_from(&mut self, shm_id_ds: PosixShmIdDs)461 pub fn copy_from(&mut self, shm_id_ds: PosixShmIdDs) {
462 self.kern_ipc_perm.uid = shm_id_ds.uid() as usize;
463 self.kern_ipc_perm.gid = shm_id_ds.gid() as usize;
464 self.kern_ipc_perm.mode = ShmFlags::from_bits_truncate(shm_id_ds.mode());
465 self.update_ctim();
466 }
467
set_mode(&mut self, shmflg: ShmFlags, set: bool)468 pub fn set_mode(&mut self, shmflg: ShmFlags, set: bool) {
469 if set {
470 self.kern_ipc_perm.mode.insert(shmflg);
471 } else {
472 self.kern_ipc_perm.mode.remove(shmflg);
473 }
474
475 self.update_ctim();
476 }
477 }
478
479 /// 共享内存权限信息
480 #[derive(Debug)]
481 pub struct KernIpcPerm {
482 /// 共享内存id
483 id: ShmId,
484 /// 共享内存键值,由创建共享内存用户指定
485 key: ShmKey,
486 /// 共享内存拥有者用户id
487 uid: usize,
488 /// 共享内存拥有者所在组id
489 gid: usize,
490 /// 共享内存创建者用户id
491 _cuid: usize,
492 /// 共享内存创建者所在组id
493 _cgid: usize,
494 /// 共享内存区权限模式
495 mode: ShmFlags,
496 _seq: usize,
497 }
498
499 /// 共享内存元信息,符合POSIX标准
500 #[repr(C)]
501 #[derive(Debug, Clone, Copy)]
502 pub struct PosixShmMetaInfo {
503 /// 最大共享内存段的大小(bytes)
504 shmmax: usize,
505 /// 最小共享内存段的大小(bytes)
506 shmmin: usize,
507 /// 最大共享内存标识符数量
508 shmmni: usize,
509 /// 单个进程可以拥有的最大共享内存段的数量,和最大共享内存标识符数量相同
510 shmseg: usize,
511 /// 所有共享内存段总共可以使用的最大内存量(pages)
512 shmall: usize,
513 _unused1: usize,
514 _unused2: usize,
515 _unused3: usize,
516 _unused4: usize,
517 }
518
519 impl PosixShmMetaInfo {
520 /// 最小共享内存段的大小(bytes)
521 pub const SHMMIN: usize = 1;
522 /// 最大共享内存标识符数量
523 pub const SHMMNI: usize = 4096;
524 /// 最大共享内存段的大小(bytes)
525 pub const SHMMAX: usize = usize::MAX - (1 << 24);
526 /// 所有共享内存段总共可以使用的最大内存量(pages)
527 pub const SHMALL: usize = usize::MAX - (1 << 24);
528 /// 单个进程可以拥有的最大共享内存段的数量,和最大共享内存标识符数量相同
529 pub const SHMSEG: usize = 4096;
530
new() -> Self531 pub fn new() -> Self {
532 PosixShmMetaInfo {
533 shmmax: Self::SHMMAX,
534 shmmin: Self::SHMMIN,
535 shmmni: Self::SHMMNI,
536 shmseg: Self::SHMSEG,
537 shmall: Self::SHMALL,
538 _unused1: 0,
539 _unused2: 0,
540 _unused3: 0,
541 _unused4: 0,
542 }
543 }
544 }
545
546 /// 共享内存信息,符合POSIX标准
547 #[repr(C)]
548 #[derive(Clone, Copy)]
549 pub struct PosixShmInfo {
550 /// 已使用id数
551 used_ids: i32,
552 /// 共享内存总量(pages)
553 shm_tot: usize,
554 /// 保留在内存中的共享内存大小
555 shm_rss: usize,
556 /// 被置换出的共享内存大小
557 shm_swp: usize,
558 /// 尝试置换次数
559 swap_attempts: usize,
560 /// 成功置换次数
561 swap_successes: usize,
562 }
563
564 impl PosixShmInfo {
new( used_ids: i32, shm_tot: usize, shm_rss: usize, shm_swp: usize, swap_attempts: usize, swap_successes: usize, ) -> Self565 pub fn new(
566 used_ids: i32,
567 shm_tot: usize,
568 shm_rss: usize,
569 shm_swp: usize,
570 swap_attempts: usize,
571 swap_successes: usize,
572 ) -> Self {
573 PosixShmInfo {
574 used_ids,
575 shm_tot,
576 shm_rss,
577 shm_swp,
578 swap_attempts,
579 swap_successes,
580 }
581 }
582 }
583
584 /// 共享内存段属性信息,符合POSIX标准
585 #[repr(C)]
586 #[derive(Debug, Clone, Copy, Default)]
587 pub struct PosixShmIdDs {
588 /// 共享内存段权限
589 shm_perm: PosixIpcPerm,
590 /// 共享内存大小(bytes)
591 shm_segsz: usize,
592 /// 最后一次连接的时间
593 shm_atime: i64,
594 /// 最后一次断开连接的时间
595 shm_dtime: i64,
596 /// 最后一次更改信息的时间
597 shm_ctime: i64,
598 /// 创建者进程id
599 shm_cpid: u32,
600 /// 最后操作者进程id
601 shm_lpid: u32,
602 /// 链接数
603 shm_map_count: usize,
604 _unused1: usize,
605 _unused2: usize,
606 }
607
608 impl PosixShmIdDs {
uid(&self) -> u32609 pub fn uid(&self) -> u32 {
610 self.shm_perm.uid
611 }
612
gid(&self) -> u32613 pub fn gid(&self) -> u32 {
614 self.shm_perm.gid
615 }
616
mode(&self) -> u32617 pub fn mode(&self) -> u32 {
618 self.shm_perm.mode
619 }
620 }
621
622 /// 共享内存段权限,符合POSIX标准
623 #[repr(C)]
624 #[derive(Debug, Clone, Copy, Default)]
625 pub struct PosixIpcPerm {
626 /// IPC对象键值
627 key: i32,
628 /// 当前用户id
629 uid: u32,
630 /// 当前用户组id
631 gid: u32,
632 /// 创建者用户id
633 cuid: u32,
634 /// 创建者组id
635 cgid: u32,
636 /// 权限
637 mode: u32,
638 /// 序列号
639 seq: i32,
640 _pad1: i32,
641 _unused1: usize,
642 _unused2: usize,
643 }
644
645 impl PosixIpcPerm {
new(key: i32, uid: u32, gid: u32, cuid: u32, cgid: u32, mode: u32) -> Self646 pub fn new(key: i32, uid: u32, gid: u32, cuid: u32, cgid: u32, mode: u32) -> Self {
647 PosixIpcPerm {
648 key,
649 uid,
650 gid,
651 cuid,
652 cgid,
653 mode,
654 seq: 0,
655 _pad1: 0,
656 _unused1: 0,
657 _unused2: 0,
658 }
659 }
660 }
661