Rust Linux 消息队列 组件

2023-12-14 13:43:58
use libc::{c_int, c_long, c_void, IPC_CREAT, c_char, IPC_RMID, key_t, size_t, ssize_t};
use std::ffi::CString;
use std::mem::size_of_val;
use libc::{strerror,sprintf};

#[repr(C)]
struct MsgBuffer {
    msg_type: c_long,
    buffer: [c_char;512],
}

impl MsgBuffer {
    fn new(msg_type:c_long,buffer:&str)-> MsgBuffer{
        let mut tmp:[c_char;512] = [0;512];
        let c_msg = CString::new(buffer).expect("Msg Buffer");
        unsafe { sprintf(tmp.as_mut_ptr(), c_msg.as_ptr());}
        MsgBuffer{
            msg_type,
            buffer:tmp
        }
    }
}
#[repr(C)]
#[derive(Debug)]
struct MsqidDs {
    msg_perm: ipc_perm,
    msg_qnum: libc::c_ulong,
    msg_qbytes: libc::c_ulong,
    msg_lspid: libc::pid_t,
    msg_lrpid: libc::pid_t,
    msg_stime: libc::time_t,
    msg_rtime: libc::time_t,
    msg_ctime: libc::time_t,
    __msg_cbytes: libc::c_ulong,
    msg_qspid: libc::pid_t,
    msg_qrpid: libc::pid_t,
    __pad5: [libc::c_ulong; 3],
}

#[repr(C)]
#[derive(Debug)]
struct ipc_perm {
    __key: libc::key_t,
    uid: libc::uid_t,
    gid: libc::gid_t,
    cuid: libc::uid_t,
    cgid: libc::gid_t,
    mode: libc::mode_t,
    __seq: libc::c_schar,
}

#[allow(unused)]
extern "C" {
    fn ftok(path: *const c_char, flag: c_int) -> key_t;
    fn msgget(key: key_t, flags: c_int) -> c_int;
    fn msgrcv(id: c_int, buffer: *mut c_void, size: size_t, msg_type: c_long, flag: c_int) -> ssize_t;
    fn msgsnd(id: c_int, buffer: *const c_void, size: size_t, flag: c_int) -> c_int;
    fn msgctl(id: c_int, flag: c_int, sqid: *mut MsqidDs);
}

#[allow(unused_attributes,dead_code)]
struct UnixMsgQueue {
    key: key_t,
    index: c_int,
    msg_type: c_long,
    block: c_int,
    flag: c_int,
    err_code: c_int,
}


#[allow(unused_attributes,dead_code)]
impl UnixMsgQueue {
    fn new(path: &str, key_number: c_int, msg_type: c_long, flag: c_int) -> Self {
        let c_msg =CString::new(path).expect("UnixMsgQueue path invald");
        let  key =
            unsafe {
                ftok(c_msg.as_ptr(), key_number)
            };
        UnixMsgQueue {
            key,
            index: 0,
            msg_type,
            block: 0,
            flag,
            err_code: unsafe { *libc::__error() },
        }
    }
    fn open(&mut self) -> c_int {
        unsafe {
            self.index = msgget(self.key, self.flag);
            self.err_code = *libc::__error();
        }
        self.index
    }
    fn read(&self, buffer: *mut c_char, size: size_t) -> c_int {
        let ret = unsafe {
            msgrcv(self.index, buffer as *mut c_void, size, self.msg_type, self.block)
        };
        ret as c_int
    }
    fn write(&self, buffer: *const c_char, size: size_t)->c_int {
        let ret = unsafe {
            msgsnd(self.index, buffer as *const c_void, size, self.block)
        };
        ret
    }
    fn no_block(&mut self) {
        self.block = 1;
    }
    fn close(&mut self) {
        unsafe {
            msgctl(self.index, IPC_RMID, std::ptr::null_mut());
        }
    }
    fn error(&mut self,err:&mut String){
        let _msg = unsafe { CString::from_raw(strerror(*libc::__error())) };
        let __msg = _msg.into_string().expect("Error get");
        err.clone_from(&__msg);
    }
}

#[cfg(feature = "main")]
impl Drop for UnixMsgQueue {
    fn drop(&mut self) {
         self.close();
    }
}

fn main() {
    let mut msg = UnixMsgQueue::new(&"/hc".to_string(), 48, 10, 0666 | IPC_CREAT);
    let mut err = String::new();
    if msg.err_code < 0 {
        msg.error(&mut err);
        println!("{}",err);
        return;
    }
    if msg.open() == -1 {
        msg.error(&mut err);
        println!("{}",err);
        return;
    }
    let msg_buffer = MsgBuffer::new(10,"hello world");
    msg.write(std::ptr::addr_of!(msg_buffer) as *const c_char, size_of_val(&msg_buffer));
}

事实证明强制类型转换,好用
在这里插入图片描述

文章来源:https://blog.csdn.net/weixin_45647912/article/details/134916321
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。