Question

I want to achieve IPC between kext and application on Mac os. I get some problems when I try to transfer data from app to kext.

Some examples on internet need more system functions for implementing Mach IPC programming on Mac like setting up a Server (bootstrap_create_service) or getting Server port (bootstrap_look_up). However I can not use other framework or system standard libs except kernel.framework for kext programming.

So here is my question: is there any alternative way to get system level support (like bootstrap_create_service function) in kext or other method to achieve IPC in kernel.framework??

Thanks a lot..

Besides, in kernel.framework, I can't use mmap(), open() to share memory between kext and app.

One example from http://flylib.com/books/en/3.126.1.90/1/ : like:

server side code :

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;

client side code :

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);
Was it helpful?

Solution

In my own work in developing Kernel Extensions, Apple has really been pushing developers towards using "Kernel Control" sockets, which are elaborated upon here. That's appropriate for Network Kernel Extensions, while for other kexts, you have a few other options which include BSD notifications, kernel queues & events, file system events, etc. These options (plus a few others you might recognize) are described in this Apple documentation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top