Reputation: 353
I'm trying to understand basics of C, volatile
keyword exactly.
It doesn't seem to work as I thought. I read somewhere:
volatile
specifies that value associated with the var can be modified by action other than those in the nearby code. When a var is declaredvolatile
, the compiler reloads the value from
memory each time it is accessed by the program. This prevents optimization by optimizing compilers. It's mainly used to ensure predictable program behavior.
I've got two programs, compiled from two different .c
files.
start_loop
has global int
variable called done
with 0
as initial value and infinite loop which should test if done
value have been changed to 1
. Also it outputs address of the done
variable to stdout
.
start_loop
program:
#include <stdio.h>
#include <time.h>
volatile int done = 0;
void delay(int seconds){
// some logic for time delay here
}
void main() {
while (done !=1){
delay(4);
printf("adress of `done`: %p\nvalue: %d\n", &done, done);
}
}
And change_done_var_value
program which should get the address of the done
variable as main
argument and change it from 0
to 1
.
Thus infinite loop in start_loop
program should check value of done
and exit the program.
change_done_var_value
:
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
char *str_arg_done = argv[1];
long int done_addr = (int)strtol(str_arg_done, NULL, 16);
long int *done = (long int *)done_addr; // converting str to pointer
printf("got the address as first arg(str): %s -> address/value %p/%li\n", argv[1], done, *done);
printf("change `done` to 1?\n");
char answer = fgetc(stdin);
if (answer == 'y')
{
*done = 1;
printf("changed\nnew value: %li", *done);
}
else
{
printf("canceled\n");
}
As i've started the start_loop
program in first terminal tab i got:
4 seconds delay passed
#1
adress of `done`: 0x601048
value: 0
4 seconds delay passed
#2
adress of `done`: 0x601048
value: 0
...
In the second terminal tab i started the change_done_var_value
and passed 0x601048
to it:
got the address as first arg(str): 0x601048 -> adress/value 0x601048/0
change `done` to 1?
y
changed
new value: 1
But start_loop
program still runs:
4 seconds delay passed
#46
adress of `done`: 0x601048
value: 0
It seems that the change_done_var_value
program got the right address
value cause it shows right 0
value while dereferencing pointer to done
variable..
What do i need to do to make things work(to change value of done
from change_done_var_value
and stop the executing of thestart_loop
program)?
Or it doesn't work like this..
Upvotes: 0
Views: 764
Reputation: 607
If I understand right, you try to use memory from one program in another program? "It doesn't work like this" on any modern operating system because programs (or better: "processes") are encapsulated purposefully this way that they can't access the memory of other processes without operating-system-specific interprocess communication library functions. You can read more about them and how to use them in C in a Linux-based operating system on this website:
Linux Interprocess Communications
I'm sorry that I can't elaborate further since I never used internal interprocess communication on a common Desktop Operating System yet.
There is also a more heavy-weight option to use the socket API (which generally can be used even accross a network of distinct PCs all over the world). Using the socket API is not difficult and is taught in network lecture courses in university. You then get "server" and "client" programs and you have to take care about some "primitives" which must be called in a specific order. A common source of tutorials seems to be the Beej Guide .
This protection mechanism is called memory virtualization. It makes that every process uses its very own virtual address space which is not equal to the one of other processes. Or brief: the same addresses in different programs will lead to separate physical addresses in the real memory.
In my opinion the design mistake here is to compile two different programs to achieve the task. The usual appraoch would be to compile only one single program which uses multi-threading (that means multiple threads of execution) because multi-threading is more light-weight than interprocess communication and maybe easier to use (at least I know how to do it). For multi-threading, you can use the pthread library in Linux-based systemes which can be included into your program with the -pthread command line option when I remember correctly).
Happy coding!
Upvotes: 3
Reputation: 61519
action other than those in the nearby code
Yes; this means things that are able to modify the corresponding chunk of memory. Most often, this will be a different thread within the same program. In some very specific platform-specific circumstances, you might arrange for a variable to be in a specific location that has a special meaning to the OS (or to the hardware); for example, on an old handheld or console you could read from a virtual memory location that represents an I/O register, in order to learn what button was pressed on the keypad. By using volatile
, the compiler will understand that the value has to be checked, because the hardware may have written to that memory and your program depends on knowing about the change.
On a modern desktop computer, programs have memory protection and memory space virtualization. They cannot easily look at each others' data, and will typically need some special arrangement/permission to do so. But even when it is possible, you cannot simply check on the other program's variable by using its name - the name is only meaningful to the compiler; it is not an actual part of the compiled program (although a debug-mode compilation might try to make it behave that way a little bit).
Upvotes: 4