There are at least two ways to run a program in background under Linux:
program param1 param2 param3 &.
screen -m -d program param1 param2.
But we aren't programmers to count on the user to run our program in one of these ways. I'll show you how to make you program put itself in the background. We're first going to use the daemon system call (see: man 3 daemon) from the C library. This is why the program writing process will be different than usually:
To see that our daemon (TSR in Linux) really is working, we'll put a loop inside, which displays a message once in a while. To make a pause in execution, we're going to use the sys_nanosleep system function (number 162).
As you can see on the manual page, the daemon function accepts 2 integers (DWORDs) as parameters:
After saying all this, it's time to move on to the example program. Its job is to go into
daemon mode and infinitely display the given message each 5 seconds. Thus, the fact that the program
is working, will be visible on the terminal on which the program was started. The program itself
will also be visible on the processes list (ps -A
command). The only way to
stop it will be to kill it using the kill command.
Here's the code in NASM syntax:
; Program going into daemon mode ; ; Author: Bogdan D., bogdandr (at) op.pl ; ; assemble: ; nasm -f elf -o demon.o demon.asm ; gcc -o demon demon.o extern daemon ; external function declaration section .text ; beginning of the code section global main ; the symbol "main" must be global ; for GCC to see it main: push dword 1 ; second parameter push dword 1 ; first parameter call daemon ; calling the daemon function add esp, 8 ; removing parameters from the stack ; interval between consecutive messages ; will last for 5 seconds and 0 nanoseconds: mov dword [t1+timespec.tv_nsec], 0 mov dword [t1+timespec.tv_sec], 5 .petla: mov eax, 4 ; file writing function mov ebx, 1 ; standard output mov ecx, napis ; what to write mov edx, napis_dl ; length of the message int 80h mov eax, 162 ; sys_nanosleep mov ebx, t1 ; wait for this long mov ecx, 0 ; address of a second timespec structure for the result int 80h ; make the pause... jmp .petla ; start all over again.... ; the below code will never be executed mov eax, 1 xor ebx, ebx int 80h ; exit the program section .data napis db "Your daemon is speaking.", 10 napis_dl equ $ - napis struc timespec ; timespec structure definition ; (anly as a data type) .tv_sec: resd 1 .tv_nsec: resd 1 endstruc t1 istruc timespec ; create the t1 variable as a whole ; timespec structure
Assembling and linking goes like this:
nasm -f elf -o demon.o demon.asm gcc -o demon demon.o
One thing needs to mentioned: the sole fact that a program is a daemon does NOT mean that it is working with root privileges (and whole of the system security is useless).
The daemon function is from the C library, but you can transform it into code which uses only the int 80h. The code of the function is in the misc/daemon.c file in the glibc library sources. It is not long and it can be easily transformed into the following macro:
%macro daemon 2 ; first parameter: nochdir - not to change the working ; directory to the root directory? ; second parameter: noclose - not to close stdin and stdout? mov eax, 2 int 80h ; sys_fork cmp eax, 0 jl %%koniec ; EAX < 0 means error test eax, eax jz %%dalej ; EAX = 0 in the child process ; EAX > 0 in the parent process mov eax, 1 xor ebx, ebx int 80h ; sys_exit - parent finishes work %%glowny: db "/", 0 %%devnull: db "/dev/null", 0 %%dalej: mov eax, 66 ; sys_setsid int 80h ; create a new session and set GID cmp eax, 0 jl %%koniec ; EAX < 0 means error %if %1 = 0 mov eax, 12 ; sys_chdir mov ebx, %%glowny int 80h ; change directory to root %endif %if %2 = 0 ; open /dev/null: mov eax, 5 mov ebx, %%devnull mov ecx, 2 mov edx, 0 int 80h cmp eax, 0 jl %%koniec ; EAX < 0 means error mov ebx, eax ; EBX = /dev/null descriptor ; duplicate the standard input, output and error output ; descriptors to an open /dev/null descriptor and close ; the descriptor after this mov eax, 63 mov ecx, 0 ; input int 80h mov eax, 63 mov ecx, 1 ; output int 80h mov eax, 63 mov ecx, 2 ; error output int 80h mov eax, 6 int 80h ; close /dev/null %endif %%koniec: %endmacro ; usage: daemon 1, 1 ; no PUSH and ADD ESP
No we can go back to the old program type, where the start symbol was _start and linking was done with LD, and not GCC with the C library.