Quote:
Originally Posted by RudyMartin
I was about to say something like nominalanimal said but since I'm new to this forum I don't want to sound rude in any way.
|
Sorry about that. I did not intend to be rude; I was genuinely puzzled. If I offended anyone, I want to apologize.
Quote:
Originally Posted by RudyMartin
2) I fail to see clearly the real problem to solve (real world I mean, not a mathematics's toy case). If I were you I would start all over stating the problem and what have you investigated so far besides the code you posted.
|
I whole-heartedly agree. newbie14, could you please start a new thread, and explain the problem you are trying to solve? Additional information, like approaches you have already considered, and technical or organizational limitations, are very important, too. Most likely there are a number of different solutions.
In the past year, in threads I've participated in, usually a few different approaches are first suggested, and then the OP or discussers pick one that seems to suit the situation best. The important thing is that different people have different experiences, and combining all that is likely to give a fuller picture than just listening to a single expert. I've programmed both proprietary and open source software for two decades now,
and I still learn new things when discussing different approaches to problems here. Every time. I've learned to not rely on
length of experience, but the
variety. And that is what LQ can provide for you, if you can just pose an interesting enough problem.
As a practical example, let me describe you a pretty esoteric way to monitor the progress of a process. I don't really think it is a suitable solution for this problem, but it is very simple to implement, quite robust, and not something most programmers would think of.
First, in your process to be monitored, you use compiler-provided atomic built-ins to update the integer value that is monitored. (The ones I prefer to use due to their widespread support are the
__sync variety; however, the latest C and C++ include
__atomic ones, which will become very widely supported in the next couple of years.) In short:
Code:
/* Global variable(s) -- here, an array of five values.
* Note that the C standard says that {0} initializes any
* array, regardless of types, to all zero bits. */
#define MONITORED_VALUES 5
static volatile long monitored_value[MONITORED_VALUES] = { 0 };
/* How to atomically increment it */
__sync_add_and_fetch(&monitored_value[N], (long)increase_by_amount);
This works even if you have multiple threads modifying the value at the same time. No locks are needed. Second, you pick a realtime signal number -- realtime signals are queued, so you don't lose one even if you happen to get more than one at the same time --, and set a very simple handler to it: When it receives a signal, it responds to the sender with the same signal, but with the monitored value as a payload. Since there is only one integer per signal, the incoming signal will specify the variable (as an index, for example). Note that I'm using the
long type, since in Linux, pointers and long are always the same length (all Linuxes are either ILP32 or LP64).
The sigaction-type signal handler is rather simple:
Code:
#include <signal.h>
#include <errno.h>
void signal_responder(int signum, siginfo_t *info, void *data)
{
const long index = (long)data;
if (index >= 0L && index < MONITORED_VALUES) {
union sigval response;
response.sival_ptr = (void *)__sync_or_and_fetch(&monitored_value[index], 0L);
sigqueue(info->si_pid, signum, response);
}
}
/* Signal handler installer */
int install_signal_responder(const int rtsignum)
{
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_sigaction = signal_responder;
act.sa_flags = SA_RESTART | SA_SIGINFO;
if (sigaction(SIGRTMIN + rtsignum, &act, NULL) == -1)
return errno;
return 0;
}
Of course, in the program you must then remember that any blocking call (listed in
man 7 signal,
Interruption of System Calls ... section), can return -1 with errno set to EINTR, if the signal delivery interrupts the blocking call. This is most important with read()/write() calls, but affects a number of other library functions too.
Any process that can send signals to that process can then monitor the designated integer values simply by setting a corresponding signal handler (to catch the value in the data pointer), and using
sigqueue() in similar fashion as above. (If you want to do it carefully, it takes a bit more code than above, but it's pretty straightforward. The main issue is to take into consideration that the target process might not answer, or that you might get a spurious belated answer when not expecting one.)
Like I said, the above is quite esoteric. I'm not sure if there is any situation where it might be the preferred one -- perhaps on some embedded architecture with very expensive threads (in computing terms).
The most
versatile version I can think of is to have a named pipe (usually
/var/run/programname.state or similar), and a separate thread in a loop. In the loop, the thread will open the named pipe, constructs the current state as a short text messge (< 512 characters), writes it into the pipe using a single syscall, then closes the named pipe. The open will block until a reader opens the pipe. This way, you can read the named pipe from any other process easily, just as if it was a plain text file -- even using things like
state=$(cat /var/run/programname.state) in Bash -- to retrieve the progress. (Having Unix time as part of the response is very useful when measuring the progress.)
While this approach requires minimal thread support (linking against pthreads), it does not limit the main program any more than the signal approach. You should still use atomic built-ins to update the integers monitored. In the looping thread, you'd best use
snprintf(), but if you want to do it the hard way, you can construct the buffer backwards using minimal but extremely efficient code (for integer values and strings only, though).
Again, this named pipe thing is just the most versatile. I'm sure that there are a large number of monitoring problems where there are much better alternatives. The problem is, we have no idea what your original problem you're trying to solve really is, so anything we might suggest is most likely suboptimal.