#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/inotify.h>
void get_event (int fd, const char * target);
void handle_error (int error);
/* ----------------------------------------------------------------- */
int main (int argc, char *argv[])
{
char target[FILENAME_MAX];
int result;
int fd;
int wd; /* watch descriptor */
if (argc < 2) {
fprintf (stderr, "Watching the current directory\n");
strcpy (target, ".");
}
else {
fprintf (stderr, "Watching %s\n", argv[1]);
strcpy (target, argv[1]);
}
fd = inotify_init();
if (fd < 0) {
handle_error (errno);
return 1;
}
wd = inotify_add_watch (fd, target, IN_ALL_EVENTS);
if (wd < 0) {
handle_error (errno);
return 1;
}
while (1) {
get_event(fd, target);
}
return 0;
}
/* ----------------------------------------------------------------- */
/* Allow for 1024 simultanious events */
#define BUFF_SIZE ((sizeof(struct inotify_event)+FILENAME_MAX)*1024)
void get_event (int fd, const char * target)
{
ssize_t len, i = 0;
char action[81+FILENAME_MAX] = {0};
char buff[BUFF_SIZE] = {0};
len = read (fd, buff, BUFF_SIZE);
while (i < len) {
struct inotify_event *pevent = (struct inotify_event *)&buff[i];
char action[81+FILENAME_MAX] = {0};
if (pevent->len)
strcpy (action, pevent->name);
else
strcpy (action, target);
if (pevent->mask & IN_ACCESS)
strcat(action, " was read");
if (pevent->mask & IN_ATTRIB)
strcat(action, " Metadata changed");
if (pevent->mask & IN_CLOSE_WRITE)
strcat(action, " opened for writing was closed");
if (pevent->mask & IN_CLOSE_NOWRITE)
strcat(action, " not opened for writing was closed");
if (pevent->mask & IN_CREATE)
strcat(action, " created in watched directory");
if (pevent->mask & IN_DELETE)
strcat(action, " deleted from watched directory");
if (pevent->mask & IN_DELETE_SELF)
strcat(action, "Watched file/directory was itself deleted");
if (pevent->mask & IN_MODIFY)
strcat(action, " was modified");
if (pevent->mask & IN_MOVE_SELF)
strcat(action, "Watched file/directory was itself moved");
if (pevent->mask & IN_MOVED_FROM)
strcat(action, " moved out of watched directory");
if (pevent->mask & IN_MOVED_TO)
strcat(action, " moved into watched directory");
if (pevent->mask & IN_OPEN)
strcat(action, " was opened");
/*
printf ("wd=%d mask=%d cookie=%d len=%d dir=%s\n",
pevent->wd, pevent->mask, pevent->cookie, pevent->len,
(pevent->mask & IN_ISDIR)?"yes":"no");
if (pevent->len) printf ("name=%s\n", pevent->name);
*/
printf ("%s\n", action);
i += sizeof(struct inotify_event) + pevent->len;
}
} /* get_event */
/* ----------------------------------------------------------------- */
void handle_error (int error)
{
fprintf (stderr, "Error: %s\n", strerror(error));
} /* handle_error */
/* ----------------------------------------------------------------- */
Wednesday, December 05, 2007
Linux inotify example
Monday, September 10, 2007
Just for fun
You have 20 votes left today.
You gained 15 experience points, isn't that nice?
Congratulations, you have been promoted to Chaplain!
You have 598 points until level 12 - Deacon.
That is from 272 writeups in about a year-and-a-half.
I wish there was a site like perlmonks for PHP!
Friday, August 31, 2007
Parallelism
The "free lunch" for developers really is over, and the industry will not know what hit it. Software design and building is about to change, and it will be painful. Strangly, a programmer who had been asleep for 20 years and has suddenly awoke would not see anything new. That programmer might well be better equipped for the multi-core world than those that "kept current". Why? Because the skills practiced then will be even more important now, and the sloppy programming that has become so commonplace will no longer do the job.
Revealing comment:
The lead Intel instructor (an authority on parallel processing) was asked how people who have built everything on OO would cope with parallel processing. The answer was: "They are screwed!".
Now you might say that we have been doing multi-threading for years. Yes, but that is not parallel processing. Multi-threading is usually about splitting I/O tasks: GUI windows, overlapped comms and disk I/O are typical. Parallel processing is about splitting (decomposing) processor tasks, which is a whole new barrel of fish. At least, it is for most people.
This revolution has started, but is not yet in full flow, and won't be for a couple of years. The reason is that there is well enough work for an extra CPU with other processes, like services, and the multi-threading we have right now. The real need willl be with quad and 8 (oct?)-core processors.
Watch this space
Tuesday, July 10, 2007
The real jungle
I found Singapore to be hot and steamy, and I am talking about the climate. The place has still not shaken off its colonial past. Its own character does come through sometimes, and more power to it. The people seem to be friendly and open without the hang-ups of many large cities. Of course I was only there for a week and I only saw a small part of it.
As usual I looked at scripts that delegates brought in. I have also had a couple of scripts from other people recently. I see very common bad practices regularly:
No use warnings
No use strict
All production scripts should have these set.
Calling subroutines using the & prefix. Why do people do this? Because that is the way we used to do it in perl 4, and people do not update their skills. The & prefix ignores prototype checking, and passes the current value of @_ into the call if no other argument is specified. Don't do it!
Calling external programs instead of Perl built-ins. I have seen `date` used instead of localtime(), `cd $dir`, `pwd`, `mkdir`, `rm`, `egrep`, and so on. This is not just lazy, it is grossly inefficient. It is also a security risk, by the way. I published a list of UNIX commands and perl equivalents, I will try and update it soon.
Monday, June 25, 2007
The threading jungle
Multi-threading has been around a long time. I first heard the term in the mid-1980s when discussing how ICL were going to host UNIX on VME. The first real implementation I saw was on Apollo NCS, a system that had many innovative features. ICL, VME, and Apollo have all gone, victims of acquisitions. Threads remain.
Multi-threading hit the mainstream with Windows NT, the system was built on it. The consensus around us UNIX hackers was that Microsoft had to encourage threads because their processes were so inefficient - no fork/exec you see. Probably utter twaddle; you know what UNIX hackers are.
Threads brought synchronisation problems. Of course they did. System programmers were no strangers to this type of issue, just the context of threads was new(ish). Way back when, on ICL VME, all we had were "test and set" and "decrement and set" instructions that were atomic. When I were a lad we had to build our own primitives, there was a particularly handy instruction that let you not only raise an interrupt (event/signal, whatever) but allowed you to send a two-word data block with it. Kids of today … don't know they're born… forty miles 't pit… etc.
I got to write real synchronisation primitives when I did the VME port of the MIMER RDBMS in the early '80s. There is nothing like having to write the damn things to understand how they work. I did not design them, I hastily add - that was done by some egg-head at
First rule when writing co-operating threads: things only go wrong at the worse possible moment. And that is usually after the thing has gone into production.
The Windows APIs are fairly easy to use, certainly compared to knitting your own. The main wrinkles in using them are a few peculiarities with the C/C++ runtime-library. I find it amazing that so many system engineers insist in using CreateThread instead of _beginthreadex. Back in Visual Studio 2.0 this was understandable, even I did it. The documentation was, um, "challenged". Now, with the MSDN, there is no excuse, the problems are well documented. Still people insist on using the wrong API. My theory, for what it is worth, is that a call to _beginthreadex, with its associated casts, looks messy on the screen, surrounded as it is by unrivalled elegance (sic). CreateThread looks good, _beginthreadex is ugly. For wotsit's sake! A thing of beauty with a memory leak is bad code, and I don't care what it looks like. Humph.
Still, you thought that was ugly? Try finding the thread-safe RTL functions in pthreads. Threads had to be retro-fitted to UNIX. Many fought against it, even the hero Torvold in the clone wars, but resistance was futile. Microsoft made life easy for us developers by having a whole special runtime-library just for multi-threading, ungrateful pups that we are. The pthreads implementations on UNIX have no such luxury. Instead there is a whole mess of different functions that are re-entrant with the _t suffix. Bye-bye portability. Finding which functions these are is a bit hit and miss, sometimes they are not in the man pages, and the standard only lists minimum requirements. Try teaching Condition Variables to a class already spaced out by mutxes. The word "predicate" makes their eyes glaze over. The fixed grin is the give-away: "Gone, solid gone", as Baloo would say. I'm sure Kipling was a coder, who else would write a whole poem about a conditional statement?
Wednesday, May 30, 2007
What I did on my holiday
2. Read "Parallel Programming in C with MPI and OpenMP" by Michael J. Quinn
Very American (the first computer was ENIAC - really?) No mention of the ICL DAP (Distributed Array Processor) - one of the first commercially available parallel processors.
Nice to see terms like "Functional Decomposition" from the 1970s recycled to be used in a parallel computing methodology.
It really bugs me when authors come up with "Creating Arrays at Run Time" and give code like this:
int *A;
A = (int *) malloc (n * sizeof(int));
When there is a perfectly good feature in C99 to do it:
The author uses for loops to access arrays quite often, but there is no mention of optimisers, and the effect of optimisations on parallel processing. Ho hum.
Thursday, April 05, 2007
Where have you been?
What's happened?
Well for starters the company I work for got taken over, and that caused a lot of dust - mostly settled now.
I have been getting into the new Korn shell 93, and I hope to post something on that soon.
Just today I got my "Happy Monkday" from perlmonks - I have been a monk for a year. Good fun!
Oh where is Perl 5.10? Soon? Please!