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);