GhaSShee


Linux


# systemd v.s. init ## traditional init ### How do Processes start Operating System ? ~~~ 1. init 1. start `/etc/rc.d/rc.sysinit` 2. start `/etc/rc.d/rc` 3. deal logins `(mingetty prefdm)` 2. rc 1. `/etc/init.d/servicename start ` ## linux convention ## if you hava a program which you want to run in init , ## write in ## /etc/rc.d/rc.local ~~~ ### see system ~~~ # service httpd status // you can see pid of httpd ### if you remove the information # rm -f /var/run/httpd/httpd.pid # service httpd status // httpd stops (you fall into no controling state) ~~~ ### unit file location | directory | explanation | |:---|:---| | /usr/lib/systemd/system | system default config file (RPM packages are here) | | /etc/systemd/system | modifications from default | | /var/run/systemd/system | the conifg file of runnning Units | ### runlevel | runlevel | Unit | |:---:|:---:| |0|poweroff.target| |1|rescue.target| |2,3,4|multi-user.target| |5|graphical.target| |6|reboot.target| ### change runlevel use `init` or `telinit` ~~~ init 1 telinit 1 ~~~ ### cgroups systemd uses cgroups cgroups (control groups) - group processes - re-distribute the cpu resorces or memory into the groups ~~~ systemd-cgls ~~~ ## use systemd | process | explanation | |:---|:---| | systemd | main daemon | | sytemd-journald | control logs which services output | | systemd-udevd | control discovering device or dynamical change of device | | systemd-logind | control login action into the system and distribute devices to users | | systemd-hostnamed | control hostnames of server | | dbus-daemon | provide the message bus which intemediates the systemd message | ### unit | .extension( unit name )| explanation | |:---|:---| | service | start the service | | target | grouped several units | | mount | mount point for file system (/etc/fstab) | | swap | validate swap (generate automatically from /etc/fstab) | | device | disk device (udev genetates it automatically if it is recognized )| ~~~ systemctl list-unit-files ~~~ ~~~ systemctl enable httpd.service systemctl disable httpd.service systemctl start httpd.service systemctl stop httpd.service systemctl restart httpd.service systemctl reload httpd.service // reload the configuration ~~~ ~~~ systemctl kill -s9 httpd.service // -s [signalName] // -s9 [signalName] : 9 is signal number ~~~ ~~~ systemctl list-units -t device -l systemctl list-units mount systemctl list-units swap ~~~ ### generator Generator generates Units dynamically ~~~ systemd-fstab-generator // refer /etc/fstab && make unit of mount and swap type systemd-cryptsetup-generator // refer /etc/crypttab && make systemd-cryptsetup@.service systemd-rc-local-generator // if /etc/rc.d/rc.local can be run , then enable autostart of rc-local.service ~~~ ## journald ~~~ journalctl -o json-pretty // output the log with json style options : --no-pager -f : waiting log and printing for the time being mode ~~~ e.g. ~~~ # journalctl -u sshd.service ~~~ # fork ## sample program fork.c ~~~ #include #include #include #include #define P_MAX 3 int main() { int pid[P_MAX]; int status, i; for ( i = 0; i < P_MAX; i++ ) { pid[i] == fork(); // fork() : system call which which duplicate the program itself and returns pid. if (pid[i] == 0) { printf("子プロセス No.%d: start\n", i); sleep(i+1); printf("子プロセス No.%d: end\n", i); exit(0); } else { printf("親プロセス: starts 子プロセス No.%d(pid=%d)\n", i, pid[i]); } } printf("waiting for the all child processed done. \n"); for (i = 0; i < P_MAX; i++) { wait(&status); } return; } ~~~ ~~~ ➜ kernel gcc fork.c -o fork ➜ kernel ./fork 親プロセス: starts 子プロセス No.0(pid=51192) 親プロセス: starts 子プロセス No.1(pid=51193) 子プロセス No.0: start 親プロセス: starts 子プロセス No.2(pid=51194) waiting for the all child processed done. 子プロセス No.1: start 子プロセス No.2: start 子プロセス No.0: end 子プロセス No.1: end 子プロセス No.2: end ~~~ todo ~~~ /usr/bin/sl ~~~ httpd forks itself and create many workers !! ~~~ #include #include #include #include #define P_MAX 3 int main() { int pid[P_MAX]; int status, i; for ( i = 0; i < P_MAX; i++ ) { pid[i] == fork(); if (pid[i] == 0) { printf("子プロセス: sl run in 5 seconds No.%d: start\n", i); sleep(5); execl("/usr/bin/sl", "/usr/bin/sl", NULL); // execl() : replace this program with the reginated program printf("this line is not executed. ") } else { printf("親プロセス: waiting for the all child processed done. \n"); wait(&status); printf("親プロセス: done.") } } return; } ~~~ ************************************************* * * * .-------. * * |/bin/bash| * * '---+---' * * | * * | .-------. * * +------>|/bin/bash| * * | fork '---+---' * * | | * * | | exec * * | v * * | .---------. * * | |/usr/bin/sl| * * | '---------' * * | child process * * | terminate. * * v * * parent process * ************************************************* ## system call flow *************************************************************** * * * * * user program --+ +---------> * * | fork ^ * * | | * * v | * * libc function- +--+ - - - - - - - - - ---+ - - - - - * * | syscall(56,...) ^ configurate errno * * | : call kernel | return() * * v | * * Linux kernel - - ---------------------+ - - - - - - * * sys_clone() sysret() * * :clone process :return to user mode * * * * *************************************************************** ## multithread ~~~ ps axuw -L // -L option : see threads @Linux // -M option : see threads @OSX ~~~ LWP : Light Weight Process ## clone.c equivalent to fork.c ~~~ #include #include #include #include int main() { //equivalent to fork() int pid = syscall(SYS_clone, SIGCHLD ,0 ,0 ,0 ,0 ); if (pid == 0){ int cpid = getpid(); printf("Child, my pid = %d\n",cpid); } else if (pid == -1) { perror("SYS_clone: "); } else { printf("Parent, child pid = %d\n", pid); } return 0; } ~~~ # system call table *************************************************************** * system call table * * +-------------+ * * |0: read | * * |1: write | * * .-----. .-----. |2: open | * * |process| --->|system | | ... | * * '-----' | call | --->|56: clone -----> sys_clone() * * ^|handler| \ | | * * / '-----' \ | ... | * * / \ | | * * .-----. / v|59: execve ----> sys_execve() * * |process| | | * * '-----' | ... | * * | | * * | | * * | | * * |312:renameat2| * * +-------------+ * * * *************************************************************** ## vDSO vDSO : virtual Dynamic Shared Object vDSO enable system call very quick ## see kernel src code ~~~ git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git ~~~ ~~~ # git blame kernel/fork.c ~~~ ~~~ # git show c6a7f572 ~~~ # Linux DLL ? quoto



Dolda2000 Dolda2000 is offline
Linux Guru
Join Date
Oct 2001
Location
Täby, Sweden
Posts
7,578
Actually, "DLL" is a generic computer science term -- A "Dynamically Linked Library" is just that, a library which, rather than being linked statically into the executable, is linked dynamically at runtime. It just so happens that Microsoft chose the generic name as the name of their implementation as well. In most Unix systems, the object and executable file format is called ELF (Executable and Linking Format). A part of ELF is the Shared Object specification (hence the filename suffix ".so"), which is the ELF implementation of DLLs. The name "shared object" is, of course, derived from the fact that they are (usually relocatable) objects that are shared by several processes simultaneously. Mind you that the ELF shared object system is far superior to Microsoft's DLL implementation, though, in that shared objects can be versioned. That way, one system can have several independent versions of the same shared object installed simultaneously, as to maintain binary compatibility for compiled executables. Microsoft's DLL implementation has no concept of versioning, so when one program overwrites an existing DLL with a newer or older version that it wants, that is what is known as "DLL Hell". It is also well worth mentioning that since the Linux kernel supports unlinking files that are in use, shared objects can be upgraded while the system is running, as opposed to Windows, which needs to be rebooted in order to upgrade or otherwise replace DLLs that are being used by system services. As for the "registry", I'd like to clarify that a bit. It's fair to say that Linux has no equivalent of the Windows registry. That's not a bad thing, however -- I'd like to point out that I strongly disagree with Krendoshazin's statement that "the windows registry is a good idea in theory", because it isn't. It's just a stupid round-about for storing the same kind of information that can already be stored in real config files. The only reason that I can find for the Windows registry is that Microsoft wanted data to be stored in a proprietary, binary format, as to prevent interoperation. It's particularly stupid since the entire registry is stored in one monolithical file, which makes it very prone to corruption. GNOME, however, has something that can be compared to the Windows registry -- "gconf". In contrast to the Windows registry, however, it actually does something that cannot easily be done with ordinary config files, though. It allows several configuration databases to be cascaded on top each other, which provides an easy and rather elegant means of storing system defaults and read-only values. I'm still in part opposed to gconf, however, for reasons that I won't go into further here. I'd surmise that KDE has something similar to gconf. As for "how Linux handles big applications", I don't really understand the question. What makes a "big application" different from a "small application"?



07-12-2005 #5
Krendoshazin Krendoshazin is offline
Linux User
Krendoshazin's Avatar Join Date
Feb 2005
Location
London, England
Posts
471
Quote Originally Posted by Dolda2000 As for the "registry", I'd like to clarify that a bit. It's fair to say that Linux has no equivalent of the Windows registry. That's not a bad thing, however -- I'd like to point out that I strongly disagree with Krendoshazin's statement that "the windows registry is a good idea in theory", because it isn't. It's just a stupid round-about for storing the same kind of information that can already be stored in real config files. The only reason that I can find for the Windows registry is that Microsoft wanted data to be stored in a proprietary, binary format, as to prevent interoperation. It's particularly stupid since the entire registry is stored in one monolithical file, which makes it very prone to corruption. That's exactly the reason why I said it was poorly implemented, but I think what you're disagreeing on really comes down to opinion, I've worked a lot with databases and know how fast a properly implemented and maintained database can be, you could teach a child to create a program to organise data from a structured ini file, but a proper database system could have it's advantages, perhaps it won't, that's yet to be seen. Great GNU/Linux references and resources: The Linux Documentation Project Rute User's Tutorial and Exposition GNU/Linux Man Pages 07-12-2005 #6



Dolda2000 Dolda2000 is offline
Linux Guru
Join Date
Oct 2001
Location
Täby, Sweden
Posts
7,578
Well, I was a bit unclear -- the "one big file" argument wasn't what I meant as the reason why the registry is a bad idea in itself. The reason that I said that the registry is a bad idea is that it confers no new functionality. It does absolutely nothing that couldn't already be done with the INI file calls. In that manner, it is a bad idea since it adds yet another useless abstraction layer to Windows, which increases the complexity of that already over-complex system and thus increases chances of fault even more. If something's useless, then you leave it out -- you don't just include it since it seems neat. Also known as the KISS principle. I think that the NIH syndrome and completely ignoring the KISS principle like this are the two primary reasons why Windows is so bad as it is.