Hi all
Can anyone give me some pointers on how to go about allocating some memory (say 20MBytes) that can be shared with other apps.
I have an app that runs all the time and logs (appends) a value every twenty seconds or so, what I need is for another app to periodically read the data that the other app
wrote to the log.
Obviously writing to hard drive is not good as after a few months the hard drive is really getting whacked and thus prefer to use RAM.
Thanks in advance.
Paulo.
Hi Paulo,
Perhaps you should give some more info on size and periodicity of your app. You write that the "server" writes a value (say: a double, 8 bytes) every twenty seconds, i.e. 34560 bytes per day. That is negligible for a hard disk, so why are you worried?
Does the "client" need the full log file, or just recent records?
Standard answers are memory-mapped files and WM_COPYDATA messages, but it really depends on the circumstances.
you can also create cutsom messages
but - if the second app fires up every 20 seconds - that's wearing on the hard drive, too - lol
you haven't saved anything by not doing it with a single app
how much data is to be saved svery 20 seconds ?
Hi
OK, more details:
App one ("server") is running all the time and writes 50 bytes every 20 seconds. (216 000 bytes per day).
App two ("client") will occasionally (perhaps 4 times a day) read the whole data so far for that day.
The days data is then flushed by the server at midnight.
I was under the impression that there are two types of wear and tear for hard drives:
1) The actual seeking for files (read or write)
2) Writing the actual data.
oh - 4 times a day isn't so bad
200 kb is nothing compared to the size of computer memory these days
WM_COPYDATA would work well - or a custom message
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644931%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms644931%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644947%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms644947%28v=vs.85%29.aspx)
http://msdn.microsoft.com/en-us/library/windows/desktop/ms649011%28v=vs.85%29.aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms649011%28v=vs.85%29.aspx)
all you need is the window handle(s) in order to send messages back and forth
when the second app fires up, it can look for the first window
there are a few ways to do that - search for it by window title, or class name, etc
FindWindow, EnumWindows and so on
Paulo,
For such a small amount of data, the simplest solution is really shared memory using a DLL. The attachment is set up for use with RichMasm, but the DLL code below works also with qEditor etc
The DLL:
include \masm32\include\masm32rt.inc
ShareLen=256*1024 ; 256k
MyData segment shared 'bss'
OneDay LABEL BYTE
ORG $+ShareLen-1 ; looks complicated but avoids a MASM bug
db ?
MyData ends
.code
GetPtr2SharedMem proc ; $export
mov eax, offset OneDay
retn
GetPtr2SharedMem endp
LibMain proc instance:DWORD, reason:DWORD, unused:DWORD
m2m eax, TRUE
ret
LibMain endp
end LibMain
Sample code calling the DLL:
include \masm32\MasmBasic\MasmBasic.inc
Init
Dll "SharedMemInDLL"
Declare GetPtr2SharedMem, 0
mov edi, GetPtr2SharedMem() ; get current content
MsgBox 0, Cat$("Write new string?"+CrLf$+edi), "Hi", MB_YESNO
.if eax==IDYES
invoke MbCopy, edi, Cat$("This string was written on "+Date$+", "+Time$), -1
MsgBox 0, "Now launch a second instance and see the string", "Hi", MB_OK
.endif
Exit
end start
dedndave
According to Microsoft:
"An application sends the WM_COPYDATA message to pass data to another application. "
Isn't this the opposite of what I need? (or perhaps I'm having a nebulous moment :biggrin: having a lot of those lately).
i.e. the receiving app should first check if the other app is running (like you say via title or class) then issue a "need some data" message.
I was thinking more along the lines of the "server" app creates an array (of sorts) in memory and saves the address of that array in a file.
It only does this at start up as the address will be valid until the app closes and relinquishes that memory and deletes the file containing the memory address.
The memory array is organized so that the first 4 bytes contains a count of the bytes that it has written so far to memory.
These 4 bytes are updated every twenty seconds once the app writes the next 50 bytes.
The second app then starts up and checks for the existence of the file which has the memory address in it.
If it exists, it reads it then reads the first 4 bytes of the array in memory telling it how many bytes it must fetch from the memory.
Perhaps a bit more convoluted but I like the isolation between the two apps, i.e. no sending of messages and waiting if the other app has got it.
@jj2007
Your DLL method look interesting, I will investigate.
A disk write must be a whole sector as a minimum, so even if you only write a single byte, a whole sector must still be written. So constantly writing will produce wear. However, a modern hard-drive should be able to handle 5 years of constant reading and writing; but why waste it. And it just means the disk is unnecessarily busy for no good reason.
The OS will cache your writes to an extent, so if you write frequently enough, they will be collected and written as full sectors, but this window is only a few seconds.
Rather than shared memory (all results lost if anything goes wrong), you can still buffer your writes, and flush to file periodically.
Allocate a medium sized buffer (16--32kB) and write your results to this every 20 seconds, then when it gets 'full,' open the file (with append) and write the collected results to the file, close the file, and start filling the buffer again. The server will be able to pick up the results from this file as needed; if you strictly want up-to-the-second results, you could have the server send a message to force the client to flush its buffer, and then the server reads from the file.
Quote from: Tedd on September 09, 2013, 11:26:09 PM
Rather than shared memory (all results lost if anything goes wrong), you can still buffer your writes, and flush to file periodically.
You should combine the two, of course. You need to add periodic saving to the simple example above, which was only intended to demonstrate how shared memory works.
Hi Tedd
Nice idea that.
Perhaps I make the buffer hold say 10 readings (~3 minutes worth of data) thereby reducing the write to file frequency by a factor
of ten and at the same time if something goes wrong with the app and it has to be restarted, not much data is lost.
Come to think of it, for 10 X 50 bytes I don't even need a buffer, just store it in a variable.
OK decided on Tedd's idea.
@jj2007
I really like your DLL, I can see several uses for it, thank you.
@dedndave
Thanks for showing me WM_USER.
I didn't know one could send private messages.
Quote from: Paulo on September 09, 2013, 11:51:54 PM
I really like your DLL
...
I didn't know one could send private messages.
Paulo,
I updated the example above, it's now "bss" to reduce the DLL size.
Note that the "server" can send messages also as a console app, e.g. for informing the "client" that new data are available (in case synchronisation is needed); but of course, there must be a message loop at the receiving end.
Thanks for the update jj2007, but why is the source in rtf format?
If some kind of server-client structure is already available, you can also use UDP for sending the log data when they arise.
Quote from: qWord on September 10, 2013, 01:22:15 AM
If some kind of server-client structure is already available, you can also use UDP for sending the log data when they arise.
Nice idea too but no server-client structure in place.
Quote from: Paulo on September 10, 2013, 01:03:15 AM
Thanks for the update jj2007, but why is the source in rtf format?
My laziness - I hate to press more than one key ;-)
OPT_Tgt dll ; target is DLL, not exe
OPT_Run GetSharedMem ; you can't run a DLL, so run the test app instead
OPT_Assembler JWasm ; ML 8+ is also OK, ML 6.15 chokes
Plain text versions attached.
i'd like to see a program written with only one key :lol:
Writing the code itself merits more than one key :greensml:
But when I am in "polishing mode", I want to see immediately the result, so one key for "build & run" is a must. Count how many menu items you have to click in your editor...
Rumours say there are coders who are so brilliant that they assemble their code and don't need to link it, let alone run the exe. But that's just rumours ;)
@jj2007
Many thanks.
@dedndave
Quote from: dedndave on September 10, 2013, 03:22:18 AM
i'd like to see a program written with only one key :lol:
Can't do it with one key, but I can with two.
The "1" key and the "0" key. :biggrin:
that's the hard way, Paulo :biggrin:
and... at some point, you are going to press Enter, i suspect
(http://umor.onru.ru/media/prikol/15816.jpg)
Who needs an ENTER key?
00001101 00001010 :biggrin:
lol
notice the guy only has 4 digits on his hand
must be a java programmer :lol:
Quote from: dedndave on September 10, 2013, 08:10:13 PM
lol
notice the guy only has 4 digits on his hand
Does it then mean that he is making a rude gesture? :biggrin:
it does look like it, huh :P
Sorry, he is the ultimate ASM programmer.
4 digits = one nybble
2 hands = 8 digits = one byte
Quote from: sinsi on September 10, 2013, 09:03:43 PM
Sorry, he is the ultimate ASM programmer.
4 digits = one nybble
2 hands = 8 digits = one byte
I'm lost for WORDS. :P
toes maybe ?
i always hated octal - don't know why :redface:
Quote from: dedndave on September 10, 2013, 10:18:29 PM
i always hated octal - don't know why
Hi,
You could always fall back to sexagesimal, as they used up
to the middle ages. Those wacky Babylonians did things their
way, ala Frank.
Cheers,
Steve
Imagine telling the wife or girlfriend (or both :biggrin:) that you are playing with sexagesimal on the computer.
You would get very strange looks. :eusa_naughty: