Hi Dimiter,
On 11/10/2016 1:27 AM, Dimiter_Popoff wrote:
> On 09.11.2016 г. 09:55, Don Y wrote:
>> On 11/8/2016 11:26 PM, Dimiter_Popoff wrote:
>>>>>> If rotating fans and rotating disk can't be used, the only alternative
>>>>>> is a Flash disk with limited number of write cycles.
>>>>>
>>>>> While generally so VM does not necessarily need to swap memory.
>>>>> If your physical memory is say 64M and your logical space is set to
>>>>> say 1G _and_ you know the 64M will never be all used up, the benefit
>>>>> of the VM is that fragmentation will be much less of a problem.
>>>>
>>>> It also lets you "write protect" memory, trap on writes to
>>>> memory that shouldn't be written, trap on writes to memory
>>>> that *should* be written, provide protected address spaces,
>>>> share memory with different processes (and in different places),
>>>> move large blocks of memory in constant time, etc.
>>>
>>> All of the protection etc., of course. When I write something new
>>> to run under dps many of the mistakes I make are captured by the
>>> "attempted access to non-allocated space, press CR to kill task" :-).
>>
>> Yes, handy at debug time but also handy for (VERY) long-lived
>> processes; "CAN'T HAPPEN" had really better NOT happen!
>
> in my experience long-lived tasks (months) just do not fail. It
> appears that if some piece of code survives a day or so chances
> are it is pretty stable and "bug free" (to the extent it will
> not fail at all). Which is not to say your scenario is not
> thinkable of course, just how things are with me.
It depends on what portions of the code are exercised in those
"months". E.g., if something only runs on the 5th Monday
of each month (and this is February) there may not *be* a
5th monday in the near future. Or, an action that the user
typically seldom invokes ("compact mailboxes"), etc.
Or, effectively exposing a hazzard that might not be encountered
in short term use (e.g., someone checking mail and then quitting
will rarely encounter a competitor process accessing the
mailbox)
I.e., the user interface can be running "forever" and still
not tickle a latent bug.
> Where I do see failures is when doing new things, e.g. a user
> using some relatively new feature. Had this recently during a
> demo - user being me. Right click on a button crashed the task,
> got that "attempted access to non-allocated space" message.
> The buttons had been there for a few years... had never seen
> that. The cause turned out to be a non-initialized pointer of
> sorts; had lay dormant (pointing to some allocated piece to
> be read to no further consequences, what was read was irrelevant)
> until some other global system change or whatever woke it up.
> Good thing the entire demo was a shiny plug-and-play affair
> (with a HPGe detector people are used to anything but that)
> so I could just laugh the bug off.
>
>> Most VMM operations happen without the developer's knowledge,
>> in my case. The OS takes care of keeping track of all the
>> magic so the developer sees a "clean" interface free of
>> hazzards, etc.
>
> Well if the developer has to allocate memory he has to say so,
> no way around that. I can't think of a cleaner and simpler way
> than have him say "give me that much" and in return "here you
> are, at this address, that much, rounded up a little".
> The developer (even if this is me) just does not think of
> physical memory at this level, just of logical.
I try to hide as much unnecessary detail as possible at
each "level" in my design. And, the "standard" interfaces
that you would expect to encounter tend to behave as you'd
expect of them.
But, a knowledgeable user can usually access the same mechanisms
via a more versatile interface for finer control over the implementation.
(However, the API doesn't REQUIRE this of all users!)
> Then if you write at a higher level - e.g. write a dps shell
> script - allocate/deallocate is completely hidden.
Yes. I use a similar philosophy throughout the design. I
expose what a developer coding at a particular level in the
design expects/needs to meet his design goals.
Someone writing for bare metal sees far more detail than
a "user" (end user/consumer) who writes nothing OR, at
best, "scripts".
Someone writing a device driver sees a different level of
abstractions and services. Writing atop the RTOS exposes
yet another API -- that of the proxy/service.
At the very top (least capable, most hand-holding) are
user "scripts". Here, the user doesn't worry about
numeric representations, memory allocation/garbage collection,
communication channels, permissions (assuming he HAS them),
crash recovery, etc.
> You "make" an object which requests memory from its "container"
> object, logs that so it will deallocate upon "remove" etc.
> It is a highly sophisticated/interconnected piece of underlying
> code really.
>
>> Its tricky to provide these hooks without EXPOSING them
>> (which would require a more sophisticated class of developer!)
>
> I just do not think of the limitations of the user. If I can
> learn to do something he/she also can (if not he is just messing
> with things he is not suppose to mess with. If something is too
> much for me to process in the time I want to spend on a given
> task it will be for someone else, too; so I just pack things
> into higher and higher level as needed, thus reducing the level
> of competence one needs to have involved in the task at hand.
Exactly. In my case, I don't want developers to have to be
concerned with the VMM and how it ties into the RTOS, etc.
If a developer (a sort of "user") wants to send a message
to a particular host/process, I don't want him to have to worry
about the mechanism for doing that: create the message and enqueue
it on the desired destination -- let the system figure out
*where* the target lies WHEN THE MESSAGE IS ACTUALLY SENT (a
target can MOVE while the message is enqueued -- why bother
the developer with handling that case?!)
Likewise, my IDL lets me define the contracts between clients and
the proxy/stub libraries for each service. E.g., if you are
MOVE-ing an object to another process (local or remote), then
the semantics of that IPC/RPC imply that the object will cease to
exist on the originating process/node. The stub generated by
the IDL will unmap the object from the caller's address space
when the routine is invoked. However, the object will persist
within the stub until it can actually be "transferred" to the
destination -- at which point, it will be deleted from the
node (if the destination was remote) or deleted from the stub's
memory space.
A whole class of errors are avoided -- those where the object is not
unmapped by the caller AFTER the RPC returns (as well as ensuring
the caller doesn't try to alter the cached object while it is waiting
to be transmitted).
OTOH, if you are *copying* the object, then it's never unmapped from
the caller's memory space -- BUT, is protected from alteration
(zero copy semantics) while the stub is waiting to copy it out
to the destination.
Again, another class of errors avoided: changing the object while
it is conceptually immutable (protecting against that would normally
require a copyout() -- even if the caller doesn't elect to alter
the data before the actual transmission occurs!)
*BUT*, the caller needs to provide a page-aligned object in order
for the system to efficiently implement this magic! (Yet I
don't want to directly expose the VMM to the caller)
> I.e. if I want to make some search utility I just write a dps
> script, I do not use my knowledge on allocate/deallocate, vpa
> language etc.
Yes, but you can do so because the machinery beneath you is already
in place and automated.
> Generally I think the assumption that a user is too stupid to
> be handed this or that so we have to stupefy the product is a
> bad approach, I have never seen anything useful come out of it
> (I don't think this is what you mean but it brought the association,
> it is one of my red buttons I suppose).
I want users (at their respective "levels" in the implementation
hierarchy) to concentrate on their objectives and not my mechanisms.
E.g., if a user wants to figure out (roughly) how many 18x18" ceramic
tiles with 1/4" grout lines are needed to tile a 19'5" x 12'2" room
(assuming a 3/8 inch border along each edge):
(19 ft 5 in - (2 * 3/8 in)) * (12 ft 2 in - (2 * 3/8 in))
/ (18 in + 1/4 in) ^ 2
will yield a dimensionless value (area/area). OTOH, omitting the
divisor would lead to an area result -- which the user could request
in any suitable "area units". It's silly to force the user to
do a bunch of trivial but error prone normalizations when the API
can handle those more reliably.