Daemon

ewillwin·2022년 5월 31일
0

System Programming Lab

목록 보기
7/15

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

Daemon Coding Rules

1. Generate a daemon process
Call fork() and exit() system call from parent process

  • Parent process is just a role to create a daemon process
  • This is a prerequisite for the creation of a new session for a daemon

2. Create a new session
pid_t setsid (void)

  • setsid() makes process the leader of the process group and session
  • On success, return the session ID of calling process
  • On error, return -1
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();
}

Cron Daemon

-> 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 어케 만드는지 모르겠음 머리아파

profile
💼 Software Engineer @ LG Electronics | 🎓 SungKyunKwan Univ. CSE

0개의 댓글