基于kernel.framework(Mac os x)的kext与app之间的IPC问题

时间:2012-12-25 16:53:34

标签: macos ipc kernel kernel-extension

我想在Mac OS上实现kext和应用程序之间的IPC。当我尝试将数据从app传输到kext时,我遇到了一些问题。

互联网上的一些示例需要更多系统功能来在Mac上实现Mach IPC编程,例如设置服务器(bootstrap_create_service)或获取服务器端口(bootstrap_look_up)。但是我不能使用除kernel.framework之外的其他框架或系统标准库来进行kext编程。

所以这是我的问题:有没有其他方法可以在kext或其他方法中获得系统级支持(如bootstrap_create_service函数)以在kernel.framework中实现IPC?

非常感谢..

此外,在kernel.framework中,我不能使用mmap(),open()在kext和app之间共享内存。

http://flylib.com/books/en/3.126.1.90/1/的一个例子: 像:

服务器端代码:

char *ptr;
kern_return_t kr;
mach_vm_address_t address = 0;
memory_object_size_t size = (memory_object_size_t)vm_page_size;
mach_port_t object_handle = MACH_PORT_NULL;
msg_format_request_r_t recv_msg;
msg_format_response_t send_msg;
mach_msg_header_t *recv_hdr, *send_hdr;
mach_port_t server_port;


kr = mach_vm_allocate(mach_task_self(),
                      &address,
                      size,
                      VM_FLAGS_ANYWHERE);


printf("memory allocated at %p\n", (void *)address);


// Create a named entry corresponding to the given mapped portion of our
// address space. We can then share this named entry with other tasks.
kr = mach_make_memory_entry_64( (vm_map_t)mach_task_self(),  // target address map
                               &size,  // so many bytes
                               (memory_object_offset_t)address,  // at this address
                               (vm_prot_t)(VM_PROT_READVM_PROT_WRITE),  // with these permissions
                               (mem_entry_name_port_t *)&object_handle,  // outcoming object handle
                               (mem_entry_name_port_t)NULL);  // parent handle




// ideally we should vm_deallocate() before we exit
// put some data into the shared memory
ptr = (char *)address;
strcpy(ptr, "Hello, Mach!");



// become a Mach server
kr = bootstrap_create_service(bootstrap_port, SERVICE_NAME, &server_port);
//EXIT_ON_MACH_ERROR("bootstrap_create_service", kr, BOOTSTRAP_SUCCESS);


kr = bootstrap_check_in(bootstrap_port, SERVICE_NAME, &server_port);
//EXIT_ON_MACH_ERROR("bootstrap_check_in", kr, BOOTSTRAP_SUCCESS);




for (;;) {


    // server loop
    // receive a message
    recv_hdr = &(recv_msg.header);
    recv_hdr->msgh_local_port = server_port;
    recv_hdr->msgh_size = sizeof(recv_msg);


    kr = mach_msg(recv_hdr,  // message buffer
                  MACH_RCV_MSG,  // option indicating service
                  0,  // send size
                  recv_hdr->msgh_size,  // size of header + body
                  server_port,  // receive name
                  MACH_MSG_TIMEOUT_NONE,  // no timeout, wait forever
                  MACH_PORT_NULL);  // no notification port
    EXIT_ON_MACH_ERROR("mach_msg(recv)", kr, KERN_SUCCESS);  // send named entry object handle as the reply



    send_hdr = &(send_msg.header);
    send_hdr->msgh_bits = MACH_MSGH_BITS_LOCAL(recv_hdr->msgh_bits);
    send_hdr->msgh_bits = MACH_MSGH_BITS_COMPLEX;
    send_hdr->msgh_size = sizeof(send_msg);
    send_hdr->msgh_local_port = MACH_PORT_NULL;
    send_hdr->msgh_remote_port = recv_hdr->msgh_remote_port;
    send_hdr->msgh_id = recv_hdr->msgh_id;


    send_msg.body.msgh_descriptor_count = 1;
    send_msg.data.name = object_handle;
    send_msg.data.disposition = MACH_MSG_TYPE_COPY_SEND;
    send_msg.data.type = MACH_MSG_PORT_DESCRIPTOR;


    kr = mach_msg(send_hdr,  // message buffer
                  MACH_SEND_MSG,  // option indicating send
                  send_hdr->msgh_size,  // size of header + body
                  0,  // receive limit
                  MACH_PORT_NULL,  // receive name
                  MACH_MSG_TIMEOUT_NONE,  // no timeout, wait forever
                  MACH_PORT_NULL);


    // no notification port
    EXIT_ON_MACH_ERROR("mach_msg(send)", kr, KERN_SUCCESS);
}



mach_port_deallocate(mach_task_self(), object_handle);
mach_vm_deallocate(mach_task_self(), address, size);
return kr;

客户端代码:

kern_return_t kr;
msg_format_request_t send_msg;
msg_format_response_r_t recv_msg;
mach_msg_header_t *send_hdr, *recv_hdr;
mach_port_t client_port, server_port, object_handle;

// find the server
kr = bootstrap_look_up(bootstrap_port, SERVICE_NAME, &server_port);



// allocate a port for receiving the server's reply
kr = mach_port_allocate(mach_task_self(),  // our task is acquiring
                        MACH_PORT_RIGHT_RECEIVE,  // a new receive right
                        &client_port);


// prepare and send a request message to the server



send_hdr = &(send_msg.header);
send_hdr->msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MAKE_SEND);
send_hdr->msgh_size = sizeof(send_msg);
send_hdr->msgh_remote_port = server_port;
send_hdr->msgh_local_port = client_port;
send_hdr->msgh_reserved = 0;
send_hdr->msgh_id = SHM_MSG_ID;


kr = mach_msg(send_hdr,  // message buffer
              MACH_SEND_MSG,  // option indicating send
              send_hdr->msgh_size,  // size of header + body
              0,  // receive limit
              MACH_PORT_NULL,  // receive name
              MACH_MSG_TIMEOUT_NONE,  // no timeout, wait forever
              MACH_PORT_NULL);  // no notification port




do {
    recv_hdr = &(recv_msg.header);
    recv_hdr->msgh_remote_port = server_port;
    recv_hdr->msgh_local_port = client_port;
    recv_hdr->msgh_size = sizeof(recv_msg);
    recv_msg.data.name = 0;



    kr = mach_msg(recv_hdr,  // message buffer
                  MACH_RCV_MSG,  // option indicating receive
                  0,  // send size
                  recv_hdr->msgh_size,  // size of header + body
                  client_port,  // receive name
                  MACH_MSG_TIMEOUT_NONE,  // no timeout, wait forever
                  MACH_PORT_NULL);  // no notification port


    printf("recv_msg.data.name = %#08x\n", recv_msg.data.name);



    object_handle = recv_msg.data.name;
    {
        // map the specified memory object to a region of our address space
        mach_vm_size_t size = vm_page_size;
        mach_vm_address_t address = 0;


        kr = mach_vm_map( mach_task_self(),  // target address space (us)
                         (mach_vm_address_t *)&address,  // map it and tell us where
                         (mach_vm_size_t)size,  // number of bytes to allocate
                         (mach_vm_offset_t)0,  // address mask for alignment
                         TRUE,  // map it  anywhere
                         (mem_entry_name_port_t)object_handle,  // the memory object
                         (memory_object_offset_t)0,  // offset within memory object
                         FALSE,  // don't copy -- directly map
                         VM_PROT_READVM_PROT_WRITE,  // current protection
                         VM_PROT_READVM_PROT_WRITE,  // maximum protection
                         VM_INHERIT_NONE);


        // inheritance properties
        if (kr != KERN_SUCCESS)
            mach_error("vm_map", kr);
        else {


            // display the current contents of the memory
            printf("%s\n", (char *)address);




            if (argc == 2) {
                // write specified string to the memory
                printf("writing \"%s\" to shared memory\n", argv[1]);


                strncpy((char *)address, argv[1], (size_t)size);
                ((char *)address)[size - 1] = '';
            }
            mach_vm_deallocate(mach_task_self(), address, size);
        }


    }



} while (recv_hdr->msgh_id != SHM_MSG_ID);


exit(0);

1 个答案:

答案 0 :(得分:1)

在我自己开发内核扩展的工作中,Apple确实一直在推动开发人员使用"Kernel Control" sockets, which are elaborated upon here。这适用于网络内核扩展,而对于其他关键字,您还有一些其他选项,包括BSD通知,内核队列和扩展。事件,文件系统事件等These options (plus a few others you might recognize) are described in this Apple documentation