2008年10月23日 星期四

一個Linux Daemon and FIFO IPC 例子

daemon qustion-daemon (執行無帶參數) 會建立一個FIFO file "/dev/myfifo", 當執行 qustion-daemon且有帶參數就會將參數值透過FIFO 傳送給daemon,"cat /var/log/syslog | tail"就會看到傳送結果,執行步驟如下:

1. gcc -o qustion-daemon qustion-daemon.c
2. sudo ./qustion-daemon
3. sudo ./qustion-daemon hi
4. cat /var/log/syslog | tail
5. pkill -n qustion-daemon

該例子我是參考sysvinit所寫成的。



//qustion-daemon.c
#include <&sys/stat.h&>
#include <&sys/wait.h&>
#include <&stdlib.h&>
#include <&unistd.h&>
#include <&errno.h&>
#include <&stdio.h&>
#include <&time.h&>
#include <&fcntl.h&>
#include <&string.h&>
#include <&signal.h&>
#include <&sys/syslog.h&>

#define PIPE_FD 10

int pipe_fd = -1;
int count=1;
int daemon_init(void);
void sig_term(int signo);
void check_init_fifo(void);
int tellme(int argc, char **argv);

struct my_request {
int id;
char data[128];
};
int main(int argc, char *argv[]){


if (argc==2) exit(tellme(argc, argv));

if(daemon_init() == -1){
printf("can't fork self\n");
exit(0);
}
openlog("qustion-daemon", LOG_PID, LOG_USER);
syslog(LOG_INFO, "program started.");
signal(SIGTERM, sig_term);
while(1) {
sleep(1);
check_init_fifo();
}


}
int tellme(int argc, char **argv){

struct my_request request;
int fd;
memset(&request, 0, sizeof(request));

request.id=count;
strcpy(request.data,argv[1]);

if ((fd = open("/dev/myfifo", O_WRONLY)) >= 0 &&
write(fd, &request, sizeof(request)) == sizeof(request)) {


close(fd);

return 0;
}
count++;
}

int daemon_init(void)
{
pid_t pid;
if((pid = fork()) < 0) return(-1);
else if(pid != 0) exit(0); /* parent exit */
/* child continues */
setsid(); /* become session leader */
chdir("/"); /* change working directory */
umask(0); /* clear file mode creation mask */
close(0); /* close stdin */
close(1); /* close stdout */
close(2); /* close stderr */
return(0);
}
void sig_term(int signo)
{
if(signo == SIGTERM){
syslog(LOG_INFO, "program terminated.");
if(pipe_fd != -1)
close(pipe_fd );
closelog();
exit(0);
}
}


void check_init_fifo(void){
struct stat st, st2;
fd_set fds;
int n;
struct timeval tv;
FILE *fp;
char buf[256];
struct my_request request;
int quit = 0;

if (stat("/dev/myfifo", &st2) < 0 && errno == ENOENT)
mkfifo("/dev/myfifo", 0600);


/*
* If /dev/initctl is open, stat the file to see if it
* is still the _same_ inode.
*/
if (pipe_fd >= 0) {
fstat(pipe_fd, &st);
if (stat("/dev/myfifo", &st2) < 0 ||
st.st_dev != st2.st_dev ||
st.st_ino != st2.st_ino) {
close(pipe_fd);
pipe_fd = -1;
}
}

/*
* Now finally try to open /dev/initctl
*/
if (pipe_fd < 0) {
if ((pipe_fd = open("/dev/myfifo", O_RDWR|O_NONBLOCK)) >= 0) {
fstat(pipe_fd, &st);
if (!S_ISFIFO(st.st_mode)) {
syslog(LOG_INFO, "%s is not a fifo","/dev/myfifo");
close(pipe_fd);
pipe_fd = -1;
}
}
if (pipe_fd >= 0) {
/*
* Don't use fd's 0, 1 or 2.
*/
(void) dup2(pipe_fd, PIPE_FD);
close(pipe_fd);
pipe_fd = PIPE_FD;

/*
* Return to caller - we'll be back later.
*/
}
}
/* Wait for data to appear, _if_ the pipe was opened. */
if (pipe_fd >= 0) while(!quit) {

/* Do select, return on EINTR. */
FD_ZERO(&fds);
FD_SET(pipe_fd, &fds);
tv.tv_sec = 5;
tv.tv_usec = 0;
n = select(pipe_fd + 1, &fds, NULL, NULL, &tv);
if (n <= 0) {
if (n == 0 || errno == EINTR) return;
continue;
}

/* Read the data, return on EINTR. */
n = read(pipe_fd, &request, sizeof(request));
sprintf(buf,"rquest=> request.id=%d,request.data=%s",request.id,request.data);
syslog(LOG_INFO, buf);
if (n <= 0) {

if (errno == EINTR) return;
syslog(LOG_INFO, "error reading initrequest");
continue;
}
}


if (pipe_fd < 0) pause();

}

1 則留言:

匿名 提到...

Yet another technique of scaling down the maturing in our epidermis is consuming a healthy diet plan [url=http://lfcream.com]lifecell[/url] intricate called Useful Keratin and the antioxidant coenzyme q10 supplement. lifecell This http://ywashst.com emphasis a lot on their own face.