OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 3:41 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 68 posts ]  Go to page Previous  1, 2, 3, 4, 5
Author Message
 Post subject: Re: Standardized IPC protocol
PostPosted: Thu Feb 04, 2021 8:32 pm 
Offline
Member
Member

Joined: Sat Nov 21, 2009 5:11 pm
Posts: 852
Quote:
In practice handles can just be data as well. What is preventing an operating system to implement all the capabilities in user space and the kernel IPC just remains simple data transfers?

Well, then you'd be back to passing process IDs to the kernel, and every message would involve a round trip through a "system" process whose job it is to pass messages back and forth between other processes. Or with some added complexity, messages that do not involve handle transfers could be sent directly after establishing the client's identity through the system server. Sounds like it would be awkward, maybe a little too micro.


Top
 Profile  
 
 Post subject: Re: Standardized IPC protocol
PostPosted: Mon Feb 08, 2021 10:45 pm 
Offline
Member
Member
User avatar

Joined: Mon May 22, 2017 5:56 am
Posts: 812
Location: Hyperspace
I haven't fully kept up with the discussion, but just wanted to note:
Using Plan 9, I sometimes found myself wishing services knew the PIDs of clients, but it was impossible because clients could be on the other end of a network link - even a multi-hop link. This will also apply to my OS, and I guess QNX also has the issue because it too has network-transparent services.

_________________
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie


Top
 Profile  
 
 Post subject: Re: Standardized IPC protocol
PostPosted: Tue Feb 09, 2021 4:20 am 
Offline
Member
Member

Joined: Wed Apr 01, 2020 4:59 pm
Posts: 73
eekee wrote:
Using Plan 9, I sometimes found myself wishing services knew the PIDs of clients, but it was impossible because clients could be on the other end of a network link - even a multi-hop link. This will also apply to my OS, and I guess QNX also has the issue because it too has network-transparent services.


Why not make PIDs know their own hosts? Then any pid-involving call can check if the pid's host is local, and if not make an RPC.


Top
 Profile  
 
 Post subject: Re: Standardized IPC protocol
PostPosted: Thu Feb 11, 2021 5:45 pm 
Offline
Member
Member
User avatar

Joined: Mon Jun 05, 2006 11:00 pm
Posts: 2293
Location: USA (and Australia)
I finally got in two way messaging. I am happy with the API. Here is both my sync and async syntax:

Code:
   graphics_driver.CallGetScreenSize(
      GraphicsDriver::GetScreenSizeRequest(), [](
         StatusOr<GraphicsDriver::GetScreenSizeResponse> response) {
         std::cout << "Async screen size is " << response->GetWidth() << " x "
            << response->GetHeight() << std::endl;
      });

   auto screen_size = *graphics_driver.CallGetScreenSize(
      GraphicsDriver::GetScreenSizeRequest());
   std::cout << "Sync Screen size is " << screen_size.GetWidth() << " x "
      << screen_size.GetHeight() << std::endl;


I built a userspace fiber framework so when sync calls blocked, the thread could keep responding to other messages.

It was a lot of work. It's the sort of work that only people on this forum can appreciate!

_________________
My OS is Perception.


Top
 Profile  
 
 Post subject: Re: Standardized IPC protocol
PostPosted: Sat Feb 13, 2021 7:27 am 
Offline
Member
Member
User avatar

Joined: Mon May 22, 2017 5:56 am
Posts: 812
Location: Hyperspace
Congrats, Andrew! :D

moonchild wrote:
eekee wrote:
Using Plan 9, I sometimes found myself wishing services knew the PIDs of clients, but it was impossible because clients could be on the other end of a network link - even a multi-hop link. This will also apply to my OS, and I guess QNX also has the issue because it too has network-transparent services.

Why not make PIDs know their own hosts? Then any pid-involving call can check if the pid's host is local, and if not make an RPC.

Interesting question. I think it would help even in tracing a server through multiple hops.

_________________
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie


Top
 Profile  
 
 Post subject: Re: Standardized IPC protocol
PostPosted: Fri Feb 26, 2021 4:55 pm 
Offline
Member
Member
User avatar

Joined: Mon Jun 05, 2006 11:00 pm
Posts: 2293
Location: USA (and Australia)
My API for sending dynamically sized messages is more verbose than I'd like. :(

This code:
Code:
   // Create two draw calls. One at 10,10 and one at 200,200.
   Permebuf<GraphicsDriver::RunCommandsMessage> commands;
   auto command_1 = commands->MutableCommands();
   auto command_1_oneof = commands.AllocateOneOf<GraphicsCommand>();
   command_1.Set(command_1_oneof);
   auto command_1_copy_texture_to_position = command_1_oneof.MutableCopyTextureToPosition();
   command_1_copy_texture_to_position.SetSourceTexture(texture_id);
   command_1_copy_texture_to_position.SetDestinationTexture(0); // The screen
   command_1_copy_texture_to_position.SetLeftDestination(10);
   command_1_copy_texture_to_position.SetTopDestination(10);

   auto command_2 = command_1.InsertAfter();
   auto command_2_oneof = commands.AllocateOneOf<GraphicsCommand>();
   command_2.Set(command_2_oneof);
   auto command_2_copy_texture_to_position = command_2_oneof.MutableCopyTextureToPosition();
   command_2_copy_texture_to_position.SetSourceTexture(texture_id);
   command_2_copy_texture_to_position.SetDestinationTexture(0); // The screen
   command_2_copy_texture_to_position.SetLeftDestination(200);
   command_2_copy_texture_to_position.SetTopDestination(200);

   // Send the draw calls.
   graphics_driver.SendRunCommands(std::move(commands));


Is the equivalent of building a data structure that if printed to pseudo-JSON would look like:

Code:
{
  Commands: [
    {
      CopyTextureToPosition: {
        source_texture: 1,
        destination_texture: 1,
        left_destination: 10,
        top_destination: 10
       }
    },
    {
      CopyTextureToPosition: {
        source_texture: 1,
        destination_texture: 1,
        left_destination: 200,
        top_destination: 200
       }
    }
  ]
}


The Permebuf<> is what holds all the data - and the internal data is page aligned. All of the other objects are references into the Permebuf<>'s memory. When I talk to the graphic's driver, I use std::move(commands), and pages owned by the Permebuf<> get sent to the receiving process. Now I can send arbitrary sized messages between processes.

The slowest part is probably all the dynamic allocating/releasing when you create and destroy Permebuf<> objects (I also have 32-byte 'mini messages' that can live just in the stack and be sent just using registers). I'm hoping I could speed this up one day by letting userland programs keep a local pool of last released pages so we can avoid syscalls for creating and destroying small Permebufs.

_________________
My OS is Perception.


Top
 Profile  
 
 Post subject: Re: Standardized IPC protocol
PostPosted: Fri Feb 26, 2021 7:58 pm 
Offline

Joined: Wed May 07, 2008 5:06 am
Posts: 19
AndrewAPrice wrote:
My API for sending dynamically sized messages is more verbose than I'd like. :(

This code:
Code:
   // Create two draw calls. One at 10,10 and one at 200,200.
   Permebuf<GraphicsDriver::RunCommandsMessage> commands;
   auto command_1 = commands->MutableCommands();
   auto command_1_oneof = commands.AllocateOneOf<GraphicsCommand>();
   command_1.Set(command_1_oneof);
   auto command_1_copy_texture_to_position = command_1_oneof.MutableCopyTextureToPosition();
   command_1_copy_texture_to_position.SetSourceTexture(texture_id);
   command_1_copy_texture_to_position.SetDestinationTexture(0); // The screen
   command_1_copy_texture_to_position.SetLeftDestination(10);
   command_1_copy_texture_to_position.SetTopDestination(10);

   auto command_2 = command_1.InsertAfter();
   auto command_2_oneof = commands.AllocateOneOf<GraphicsCommand>();
   command_2.Set(command_2_oneof);
   auto command_2_copy_texture_to_position = command_2_oneof.MutableCopyTextureToPosition();
   command_2_copy_texture_to_position.SetSourceTexture(texture_id);
   command_2_copy_texture_to_position.SetDestinationTexture(0); // The screen
   command_2_copy_texture_to_position.SetLeftDestination(200);
   command_2_copy_texture_to_position.SetTopDestination(200);

   // Send the draw calls.
   graphics_driver.SendRunCommands(std::move(commands));


Is the equivalent of building a data structure that if printed to pseudo-JSON would look like:

Code:
{
  Commands: [
    {
      CopyTextureToPosition: {
        source_texture: 1,
        destination_texture: 1,
        left_destination: 10,
        top_destination: 10
       }
    },
    {
      CopyTextureToPosition: {
        source_texture: 1,
        destination_texture: 1,
        left_destination: 200,
        top_destination: 200
       }
    }
  ]
}




Yes, that looks rather complicated. Is there any particular reason why you are using a complex structured IPC transport layer rather than a basic unstructured one with support for structured messages left to a regular user library? Structured RPC adds overhead that is completely unnecessary for some types of servers (depending on the security model of your OS, it may make things harder to secure). Also, does your IPC transport layer have a hardcoded set of classes for each message type server in your system, or are the message classes provided by the individual servers/interface libraries? In addition, is there any reason why you didn't just make the various fields of the message arguments to the constructor rather than requiring them to be set afterwards with accessors? That would make it less verbose.

_________________
Developer of UX/RT, a QNX/Plan 9-like OS


Top
 Profile  
 
 Post subject: Re: Standardized IPC protocol
PostPosted: Fri Feb 26, 2021 9:30 pm 
Offline
Member
Member
User avatar

Joined: Mon Jun 05, 2006 11:00 pm
Posts: 2293
Location: USA (and Australia)
andrew_w wrote:
Yes, that looks rather complicated.

I want to really clean up my API.

andrew_w wrote:
Is there any particular reason why you are using a complex structured IPC transport layer rather than a basic unstructured one with support for structured messages left to a regular user library? Structured RPC adds overhead that is completely unnecessary for some types of servers (depending on the security model of your OS, it may make things harder to secure). Also, does your IPC transport layer have a hardcoded set of classes for each message type server in your system, or are the message classes provided by the individual servers/interface libraries?


I built my own IDL called Permebuf. It's mostly userspace, other than the ability to send pages to other processes, and discover named services. I have .permebuf files (here's an example of my graphics device) and I have a permebuf->C++ compiler that generates the classes aswell as server and client stubs. I tried to aim for zero serialization - that is - you read and write to the permebuf in-situ (Permebuf references are just buffer pointer + offset). Permebufs are made to be write-once data structures (you can update them, but as memory is always allocated at the end of a Permebuf, you can't release individual objects without releasing the entire Permebuf) but super fast. I was inspired by gRPC/Protobufs. The theory being that by building my OS's microkernel ecosystem around Permebufs, I could build a Permebuf->Javascript/Rust/Go/etc. compiler and any program or any server could be implemented in any language that supports Permebufs.

andrew_w wrote:
In addition, is there any reason why you didn't just make the various fields of the message arguments to the constructor rather than requiring them to be set afterwards with accessors? That would make it less verbose.


Permebufs are binary backwards compatible (that is, you can rename, add, remove fields, etc.) even though obviously this will break code that calls "SetName" if "Name" no longer exists. I'm thinking about how I could simplify it with constructors like you mentioned and possibley aggregate initialization.

_________________
My OS is Perception.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 68 posts ]  Go to page Previous  1, 2, 3, 4, 5

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 24 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group