Operating System/System Programming(Arif Butt)

Lec20) Design and Code Of Daemon Processes

Tony Lim 2021. 7. 12. 13:18

A daemon is a system process that provides services to system admin w/o human intervention (cron) , provide services to OS Kernel (paged), or communciate with other porcesses (httpd). It has following characteristics:

A daemon is long-lived , often created at system startup and runs until the system is shut down

It runs in the backgroudn and has no controlling terminal. The lack of a controlling terminal ensures that the kernel never automatically generates any terminal-related signals (such as SIGINT, SIGQUIT, SIGTSTP , SIGHUP) for a daemon.

 

cornd = a daemon that executes commands at a scheduled time

sshd = the secure shell daemon , which permits logins from remote hosts using a secure communciations protocol.

httpd = the HTTP server daemon (Apache), which servers web pages.

xinetd = the Internet super server daemon, which listens for incoming network connections on specified TCP/IP ports and lanuches appropriate server programs to handle these connections.

 

 

what Stat character stands for.

x option shows process those who doesn't have controlling terminal.

 

 

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

void create_daemon();
int main(){
   create_daemon(); 
   while(1){}
}
void create_daemon(){
//STEP-I: Make the process child of systemd
   pid_t cpid = fork();
   if(cpid > 0)
      exit(0);
//STEP-II: Close all files descriptors less 0,1,2
   struct rlimit r;
   getrlimit(RLIMIT_NOFILE, &r);
   for(int i=3; i<r.rlim_max; i++)
      close(i);
//STEP-III: Only a single instance of a daemon process should run
   int fd = open("f1.txt", O_CREAT | O_TRUNC | O_RDWR, 0666);
   if(fd == -1){perror("open");}
   struct flock lock;
	lock.l_start = 0;
	lock.l_len = 0;
	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	int rv = fcntl(fd, F_SETLK, &lock);	
   if(rv == -1){
      printf("This process is already running\n");
      close(fd);
      exit(1);
	}
	fprintf(stderr,"Daemon has started running with PID: %d\n", getpid());

//STEP-IV: Make std descriptors point to /dev/null
   int fd0 = open("/dev/null", O_RDWR);
   dup2(fd0, 0);
   dup2(fd0, 1);
   dup2(fd0, 2);
   close(fd0);
//STEP-V: Make the daemon session leader
    setsid();
//STEP-VI: Set umask to 0 and its pwd to /
    umask(0);
	chdir("/");
//STEP-VII: Ignore the SIGHUP signal
signal(SIGHUP,SIG_IGN);
}

creating daemon process

1. fork process

2. close all file descriptor that the daemon may have inherited from its parent. a daemon may nee dto kpee certain inhertied file dscriptors open , so this step is open to variation.

3. only a single instance of a daemon process should run. 

4. make file descriptors 0,1,2 of PPFDT point to the file /dev/null. 

5. detaching terminal and makes the daemon process the process group leader and session leader.

6. set the file mode creation mask to 0. to ensure that when the daemon creates files and directories they have exactly the same access privileges as mentioned in the mode specified in an open() or creat() system call

7. SIGHUP , SIG_IGN should be ignore

 

 

Systemd 

is a system and service manager for linux operating systems. whenrun as first process on boot (as PID 1), it acts as init system that brings up and maintains user space services.

The /sbin/init and /bin/systemd are both a soft link to /lib/systemd/systemd

The 2 key advantages of systemd over SYS-V init daemon are

  • Event Driven = Stuff is started at the moment when it is needed , not before and not after that
  • Fast Booting = systemd displays the login prompt within a couple of seconds , no matter if a service on a remote socket is not available

if system is enable it will start automatically when booting.

 

import socket
sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sockfd.bind(('0.0.0.0', 54154))
print("My echo server is listening on port: 54154")
while True:
	payload, client_addr = sockfd.recvfrom(1024)
	sockfd.sendto(payload, client_addr)

using UDP and sockfd is file descriptor. binding to local address and port.

1024 is buffer. receving paylaod and client address and then send back.

now let's make this to serviece.

 

 

Anatomy of a Unit file

Unit = first section found in most of the files. defiens metadata of the unit file and is used configure the relationship of this unit with other units.

Servce = applicable to service unit file only. 

Install = This is often the last optinal section and is used to define it this unit is enabled or disabled. Only units that can be enabled will have this section.

example of ssh service.

now let's make our service

[Unit]
Description=myecho service by Arif Butt
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=always
RestartSec=1
ExecStart=/usr/bin/python /usr/local/bin/myechoserver.py

[Install]
WantedBy=multi-user.target
Alias=myecho.service

sudo cp myechoserver.py /usr/local/bin

sudo cp myecho.service /etc/systemd/system/

now we can start or service with "systemctl start myecho.service"