There are 2 types of processes:
Foreground process -> Shell must wait for process termination
Background process -> Shell doesn't wait for process termination / One way to generate a background process is appending the '&' symbol to the end of the command line
Session
Session is a collection of one or more process groups
-> Session can have a single terminal (controlling terminal)
-> A single fore ground process group과 One or more background process groups로 나누어짐
What is Daemon?
Daemon is a special type of background process
-> No controlling terminal
-> Normally start at system boot and keep running forever
-> Traditionally, daemon names end with letter 'd'
-> In Windows, daemons are called service
1. Generate a daemon process
Call fork() and exit() system call from parent process
2. Create a new session
pid_t setsid (void)
if(fork() == 0){
printf("old session id : %d\n", getsid(getpid()));
if(setsid() == -1)
printf("setsid failed");
else
printf("new session id : %d\n", getsid(getpid)));
}
wait(NULL);
3. Setting a file mode mask (umask)
If the daemon process creates files, it may want to set specific file permissions
If umask value is 1, clear value; otherwise, keep value
4. Change the current working directory to the root directory
Current working directory can be unmounted
5. Unneeded file descriptor should be closed
Prevent the daemon from holding any open descriptors that it may have inherited from its parent
6. Change standard file descriptors 0, 1, 2 to /dev/null
Daemon would not require STDIN, STDOUT, STDERR
Many library functions assume that the first three descriptors are open
void main() {
unsigned int pid;
int fd0, fd1, fd2;
if((pid = fork()) != 0) exit(0);
if(setsid() < 0) exit(0);
if(chdir("/") < 0) exit(0);
umask(0);
close(0); close(1); close(2);
fd0 = open("/dev/null", O_RDWR);
fd1 = open("/dev/null", O_RDWR);
fd2 = open("/dev/null", O_RDWR);
while(1) { /* contents */ }
return 0;
}
How to handle error messages in daemon? Daemons don't have a controlling terminal
-> Solution: syslog daemon
openlog() opens a connection to the system logger
closelog() closes the file descriptor being used to write to the system logger
syslog() generates a log message
setlogmask() sets the log priority mask for the process
#include <syslog.h>
void main(void) {
setlogmask(LOG_MASK(LOG_EMERG));
openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_EMERG, "Error");
syslog(LOG_INFO, "Logging");
closelog();
}
-> Standard tool for running commands on a predetermined schedule
-> Automatically start when the system boots
-> Cron configuration file (crontab)
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
unsigned int pid;
time_t t;
struct tm *tm;
int fd;
char *argv[3];
char buf[512];
int fd0, fd1, fd2;
fd = open("./crontab", O_RDWR);
pid = fork();
if(pid == -1) return -1;
if(pid != 0)
exit(0);
if(setsid() < 0)
exit(0);
if(chdir("/") < 0)
exit(0);
umask(0);
close(0);
close(1);
close(2);
fd0 = open("/dev/null", O_RDWR);
fd1 = open("/dev/null", O_RDWR);
fd2 = open("/dev/null", O_RDWR);
t = time(NULL);
tm = localtime(&t);
while(1){
buf[0] = '\0';
int line = 3;
char *str = NULL;
size_t size = 0;
for(int i=0; i < line; i++){
getline(&str, &size, fd);
str[strlen(str) - 1] = '\0';
char *token;
char *pos = str;
int x = 0;
while((token = strtok_r(pos, " ", &pos))){
printf("%s\n", token);
argv[x] = token;
x++;
}
if((argv[0] == '*' || atoi(argv[0]) == tm->tm_min) && (argv[1] == '*' || atoi(argv[1]) == tm->tm_hour)){ //checkminute && checkhour
if((pid = fork()) == 0)
execl("/bin/sh", "/bin/sh", "-c", argv[2], (char*) NULL);
}
}
//syslog(LOG_DEBUF, "%s", buf);
t = time(NULL);
tm = localtime(&t);
sleep(60 - tm->tm_sec % 60);
}
return 0;
}
crond 어케 만드는지 모르겠음 머리아파