I got dragged into an art project for helping out firefighting messaging between some small mipsel devices running linux.
The distribution comes with microperl in its package system, however it wasn't built with select() by default, which makes it pretty much useless for writing network applications. So I was hoping to cross-compile standard perl and modules to mips, but it seemed really painful. I gave up and ended up just enabling HAS_SELECT for the cross-compiled microperl.
Now I have to use Socket.pm to actually do the networking bit. It turned out lots of crucial bits are written in xs, so I reimplemented them in pure perl. (Ya, I know it's bad to pack platform-dependent structure manually)
So I have a tiny application controlling a local led display and buttons IO device, as well as broadcasting and processing events over network, all in a few hours after I get the microperl and socket working!
Anyway, it's quite fun hacking and I am looking forward to the show itself!
Using MicroPerl for embedded is a great idea. Microperl, not just for bootstrapping anymore.
Re:microperl & sockets
yoleg on 2007-03-09T16:22:09
Hello,
I finally could make it work by using the following code (that allows my code to be rather platform-independant, if I fill in properly the first bunch of variables):
my $PF_UNIX=1;
my $AF_UNIX=$PF_UNIX;
my $SOCK_STREAM=2; # 1 for ix86, 2 for MIPS
my $SOMAXCONN=128;
my $sun_path_SIZE=2;
my $sun_family_SIZE=108;
#my $uaddr = sockaddr_un($SOCKFILE); # Create a UNIX socket (local)... not used because this requires Socket.pm... instead, we will pack the sockaddr_un structure manually as done below
sub is_little_endian {
return (unpack('c', pack('s', 1)));
}
my $sun_path_pack = "I";
($sun_path_SIZE == 1) && ($sun_path_pack = "C");
($sun_path_SIZE == 2) && ($sun_path_pack = (is_little_endian() ? "v" : "n"));
($sun_path_SIZE == 4) && ($sun_path_pack = (is_little_endian() ? "V" : "N"));
# This contains $AF_UNIX (it is the.sun_family field of sockaddr_un) + .sun_path field of sockaddr_un
$uaddr = pack($sun_path_pack . " a" . $sun_family_SIZE, $AF_UNIX, $SOCKFILE);
My $uaddr then contains the right struct to create the socket...
$SOMAXCONN is used later to avoid depending on Socket.pm only for SOMAXCONN
The rest of the variables:
$PF_UNIX=1;
$SOCK_STREAM=2;
$SOMAXCONN=128;
...are taken from the #defines of my cross-compiler, and:
$sun_path_SIZE=2;
$sun_family_SIZE=108;
...are extracted from the size of the fields inside sockaddr_un.
To automate the discovery of the above variables, the following C file can be cross-compiled to dump the right variables on the target environment (a MIPS for me):
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#ifndef UNIX_PATH_LEN
#define UNIX_PATH_LEN (sizeof(((struct sockaddr_un *) 0)->sun_path))
#endif
int main (int argc, char **argv) {
struct sockaddr_un *sample_un_sock;
#ifdef SOCK_STREAM
printf("SOCK_STREAM=%u\n", SOCK_STREAM);
#endif
#ifdef SOMAXCONN
printf("SOMAXCONN=%u\n", SOMAXCONN);
#endif
#ifdef PF_UNIX
printf("PF_UNIX=%u\n", PF_UNIX);
#endif
printf("OFFSET for.sun_path in sockaddr_un=%u\n", (void *)&(sample_un_sock->sun_path) - (void *)sample_un_sock);
printf("SIZE for.sun_path in sockaddr_un=%u\n", UNIX_PATH_LEN);
printf("OFFSET for.sun_family in sockaddr_un=%u\n", (void *)&(sample_un_sock->sun_family) - (void *)sample_un_sock);
printf("SIZE for.sun_family in sockaddr_un=%u\n", sizeof(sample_un_sock->sun_family));
return 0;
}
Also, for cross-compiling Perl (using miniperl instead of microperl), there is a nice text describing a cross-Configure (using ssh and scp for example), to generate a config.sh matching with a remote target (for further cross-compilation).
This can be found in the Cross-compilation section of the./INSTALL text file (in perl-5.8.8)