Difference between revisions of "Linux development"
(→Kode) |
(→Sockets) |
||
(13 intermediate revisions by 4 users not shown) | |||
Line 2: | Line 2: | ||
=Application framework og GUI= | =Application framework og GUI= | ||
− | Skal du lave noget C++ til linux er der mange toolkits at vælge i mellem. Men du vil sikkert få mest success med enten [http://wxwidgets.org/ wxWidgets] eller [http://www.trolltech.com/products/qt/ Qt]. | + | Skal du lave noget C++ til linux er der mange toolkits at vælge i mellem. Men du vil sikkert få mest success med enten [http://wxwidgets.org/ wxWidgets] eller [http://www.trolltech.com/products/qt/ Qt]. Disse libraries er mere end bare GUI - det er komplette Application frameworks med klasser til håndtering af f.eks. tråde, sockets, DB adgang mm. |
=Tråde= | =Tråde= | ||
=Sockets= | =Sockets= | ||
+ | For at arbejde med socket's under linux (og sikkert også andre unix varianter) skal man bruge en række systemkald (<code>socket(2)</code>, <code>bind(2)</code>, <code>bind(2)</code>, <code>connect(2)</code>) for at få åbnet en brugbar file-descriptor der siden kan tilgåes med med <code>read(2)</code> og <code>write(2)</code>. | ||
+ | |||
+ | Disse kald kan godt være besværlige at have med at gøre og de passer heller ikke ind i object orienteret/C++ kode. Derfor kan man benytte sig et library som pakker disse kald ind i nogle klasser: | ||
+ | *http://sourceforge.net/projects/cppsocket | ||
+ | *http://www.alhem.net/Sockets/ | ||
+ | *http://linuxgazette.net/issue74/tougher.html | ||
+ | *http://asio.sourceforge.net/ <- boost style IO library | ||
+ | |||
+ | =Tid= | ||
+ | For at aflæse tiden bruges time(2) som returnerer antal sekunder siden epoch(1/1/1970) - denne kan kombineres med localtime(3) hvor at man kan aflæse minutter,timer,dage osv. | ||
+ | |||
+ | Har man brug for en højere opløsning i tiden kan man bruge gettimeofday(2), hvor man aflæser tiden i sekunder og microsekunder (siden epoch). | ||
+ | |||
+ | ==gettimeofday eksempel== | ||
+ | #include <iostream> | ||
+ | #include <time.h> | ||
+ | #include <sys/time.h> | ||
+ | |||
+ | using namespace std; | ||
+ | |||
+ | //returnerer tids-forskellen i microsekunder | ||
+ | int uTimeDiff(timeval& then, timeval& now) | ||
+ | { | ||
+ | return ( (now.tv_sec - then.tv_sec)*1000000) + (now.tv_usec-then.tv_usec); | ||
+ | } | ||
+ | |||
+ | // returnerer tids-forskellen i millisekunder | ||
+ | int mTimeDiff(timeval& then, timeval& now) | ||
+ | { | ||
+ | return uTimeDiff(then,now) /1000; | ||
+ | } | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | timeval start,now; | ||
+ | gettimeofday(&start, 0); | ||
+ | cout << start.tv_sec << "|" << start.tv_usec << endl; | ||
+ | |||
+ | for (int i=0; i<25; i++) | ||
+ | { | ||
+ | usleep(100*1000); | ||
+ | gettimeofday(&now, 0); | ||
+ | cout << "Milliseconds since start: " << mTimeDiff(start,now) << endl; | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
=Daemon= | =Daemon= | ||
Line 13: | Line 59: | ||
==Kode== | ==Kode== | ||
+ | #include <signal.h> | ||
+ | #include <fcntl.h> | ||
+ | |||
#define LOCKFILE "/tmp/myapp.lock" | #define LOCKFILE "/tmp/myapp.lock" | ||
− | + | ||
+ | #define FORK_ERROR -1 | ||
+ | #define CANT_OPEN_LOCK -2 | ||
+ | #define ALREADY_LOCKED -3 | ||
#define daemon_shutdown(x) exit(x) | #define daemon_shutdown(x) exit(x) | ||
− | + | ||
void log_message(const char *); | void log_message(const char *); | ||
− | + | ||
void signal_handler(int sig) | void signal_handler(int sig) | ||
{ | { | ||
switch(sig) { | switch(sig) { | ||
− | case SIGHUP: | + | case SIGHUP: /* this is usually used to re-load the configuration files */ |
log_message("hangup signal catched"); | log_message("hangup signal catched"); | ||
break; | break; | ||
Line 63: | Line 115: | ||
chdir("/tmp"); /* change running directory*/ | chdir("/tmp"); /* change running directory*/ | ||
− | / | + | /*attempt to create lockfile and put a file-lock on it*/ |
lfp=open(LOCKFILE, O_RDWR|O_CREAT, 0640); | lfp=open(LOCKFILE, O_RDWR|O_CREAT, 0640); | ||
if (lfp<0) /* can not open */ | if (lfp<0) /* can not open */ |
Latest revision as of 10:27, 5 March 2007
Denne side skal ses som et linux modstykke til MFC siden.
Contents
Application framework og GUI
Skal du lave noget C++ til linux er der mange toolkits at vælge i mellem. Men du vil sikkert få mest success med enten wxWidgets eller Qt. Disse libraries er mere end bare GUI - det er komplette Application frameworks med klasser til håndtering af f.eks. tråde, sockets, DB adgang mm.
Tråde
Sockets
For at arbejde med socket's under linux (og sikkert også andre unix varianter) skal man bruge en række systemkald (socket(2)
, bind(2)
, bind(2)
, connect(2)
) for at få åbnet en brugbar file-descriptor der siden kan tilgåes med med read(2)
og write(2)
.
Disse kald kan godt være besværlige at have med at gøre og de passer heller ikke ind i object orienteret/C++ kode. Derfor kan man benytte sig et library som pakker disse kald ind i nogle klasser:
- http://sourceforge.net/projects/cppsocket
- http://www.alhem.net/Sockets/
- http://linuxgazette.net/issue74/tougher.html
- http://asio.sourceforge.net/ <- boost style IO library
Tid
For at aflæse tiden bruges time(2) som returnerer antal sekunder siden epoch(1/1/1970) - denne kan kombineres med localtime(3) hvor at man kan aflæse minutter,timer,dage osv.
Har man brug for en højere opløsning i tiden kan man bruge gettimeofday(2), hvor man aflæser tiden i sekunder og microsekunder (siden epoch).
gettimeofday eksempel
#include <iostream> #include <time.h> #include <sys/time.h> using namespace std; //returnerer tids-forskellen i microsekunder int uTimeDiff(timeval& then, timeval& now) { return ( (now.tv_sec - then.tv_sec)*1000000) + (now.tv_usec-then.tv_usec); } // returnerer tids-forskellen i millisekunder int mTimeDiff(timeval& then, timeval& now) { return uTimeDiff(then,now) /1000; } int main() { timeval start,now; gettimeofday(&start, 0); cout << start.tv_sec << "|" << start.tv_usec << endl; for (int i=0; i<25; i++) { usleep(100*1000); gettimeofday(&now, 0); cout << "Milliseconds since start: " << mTimeDiff(start,now) << endl; } return 0; }
Daemon
Hvis at man laver et server program til linux, vil man som regel gerne at processen kører i baggrunden - her er et eksempel på hvordan at det kan laves:
Kode
#include <signal.h> #include <fcntl.h>
#define LOCKFILE "/tmp/myapp.lock" #define FORK_ERROR -1 #define CANT_OPEN_LOCK -2 #define ALREADY_LOCKED -3 #define daemon_shutdown(x) exit(x) void log_message(const char *); void signal_handler(int sig) { switch(sig) { case SIGHUP: /* this is usually used to re-load the configuration files */ log_message("hangup signal catched"); break; case SIGTERM: log_message("terminate signal catched...exiting"); unlink(LOCKFILE); daemon_shutdown(0); break; } } void daemonize() { int i, lfp; char str[10]; if (getppid() == 1) /* already a daemon */ return; i=fork(); if (i<0) /* fork error */ daemon_shutdown(FORK_ERROR); if (i>0) /* parent exits */ daemon_shutdown(0); /* child daemon continues */ setsid(); /* obtain a new process group */ for (i=getdtablesize(); i>=0; --i) close(i); /*close all descriptors*/ i=open("/dev/null", O_RDWR); /* handle std. io */ dup(i); dup(i); umask(027); /* set newly created file permissions */ chdir("/tmp"); /* change running directory*/ /*attempt to create lockfile and put a file-lock on it*/ lfp=open(LOCKFILE, O_RDWR|O_CREAT, 0640); if (lfp<0) /* can not open */ daemon_shutdown(CANT_OPEN_LOCK); if (lockf(lfp,F_TLOCK,0) < 0) /* can not lock */ daemon_shutdown(ALREADY_LOCKED); /* first instance continues */ sprintf(str, "%d\n", getpid() ); /* record pid to lockfile */ write(lfp, str, strlen(str) ); signal(SIGCHLD, SIG_IGN); /* ignore child */ signal(SIGTSTP, SIG_IGN); /* ignore tty signals */ signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGHUP, signal_handler); /* catch hangup signal */ signal(SIGTERM, signal_handler); /* catch kill signal */ /*this program is now a daemon*/ }