1

Mac OS で kext とアプリケーションの間で IPC を実現したいと考えています。アプリから kext にデータを転送しようとすると、いくつかの問題が発生します。

サーバーのセットアップ (bootstrap_create_service) やサーバー ポートの取得 (bootstrap_look_up) など、Mac で Mach IPC プログラミングを実装するために、インターネット上のいくつかの例では、より多くのシステム関数が必要です。ただし、kext プログラミング用の kernel.framework 以外のフレームワークまたはシステム標準ライブラリは使用できません。

ここに私の質問があります: 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);
4

1 に答える 1

1

カーネル拡張機能の開発における私自身の仕事では、Appleは実際に開発者に「カーネル制御」ソケットの使用を推進してきました。これについてはここで詳しく説明します。これはネットワークカーネル拡張に適していますが、他のkextには、BSD通知、カーネルキューとイベント、ファイルシステムイベントなどを含む他のいくつかのオプションがあります。これらのオプション(および認識できる他のいくつかのオプション)は、このAppleで説明されていますドキュメント

于 2012-12-26T02:00:26.513 に答える