Giới Thiệu về Unix Process

Là một kỹ sư lập trình hệ thống, một server guy, hay là một sys admin, sys dev, sys ops,… phần lớn thời gian bạn sẽ phải làm việc trên hệ thống Unix. Để làm việc trên Unix, chúng ta tương tác với hệ điều hành thông qua các lệnh (command). Mỗi lệnh trên Unix khi thực thi sẽ run một process hoặc một group các processes.

Trong bài viết này mình giới thiệu các kiến thức và kỹ thuật cơ bản để làm việc với Process trên Unix. Bài viết sẽ trình bày với code minh hoạ bằng Ruby (rồi bạn sẽ thấy Ruby rất đơn giản). Tất cả các code mình hoạ được chạy trên môi trường Unix (Linux của chính là Unix – nếu bạn chưa biết, vì thế đừng ngần ngại thử nó trên máy bạn).

Dù mình đã rất cố gắng, nhưng có thể vẫn có sai sót, mình rất cám ơn các ý kiến đóng góp

I. Một số kiến thức tổng quan

Tất cả các chương trình trong Unix thực chất đều là các processes. terminal bạn chạy, apache, nginx, vim, hay bất cứ lệnh nào bạn gõ vào terminal. Process chính là đơn vị cấu thành nên Unix. Nó chính là một instance của chương trình bạn viết ra. Nói cách khác mỗi dòng code của bạn, sẽ được thực thi trên một process.

Unix cung cấp tool ps để list ra tất cả các process đang chạy trên hệ thống

proc.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$> ps -e -opid,ppid,user,rss,command
PID   PPID  USER     RSS      COMMAND
1     0     root     152      init [2]
1695  1     root     428      /usr/sbin/sshd
1863  1     root     48       /sbin/getty 38400 tty1
1864  1     root     48       /sbin/getty 38400 tty2
1865  1     root     48       /sbin/getty 38400 tty3
1866  1     root     48       /sbin/getty 38400 tty4
1867  1     root     48       /sbin/getty 38400 tty5
1868  1     root     48       /sbin/getty 38400 tty6
24477 1695  root     2888     sshd: vagrant [priv]
24479 24477 vagrant  1996     sshd: [email protected]/0
24480 24479 vagrant  2328     -bash
24591 24480 vagrant  1060     ps -e -opid,ppid,user,rss,command

Ở đây, mình chạy lênh ps và show ra các thuộc tính pid,ppid,user,rss,command của process (chú ý (1) ps có rất nhiều option để chạy, nếu bạn muốn hiểu chỉ tiết, hãy sử dụng man ps để biết, (2) kểt quả trả về chỉ là một phần các process trên máy mình). Các thông tin mình muốn hiện thị ở đây bao gồm:

  1. PID – Process ID (id của process),
  2. PPID – Parent Process ID (id process cha của process đó),
  3. USER (tên user trên Unix start process),
  4. RSS (Resident Set Size) có thể coi bộ nhớ mà process sử dụng,
  5. COMMAND – command mà user sử dụng để chạy processs

Chú ý rằng dòng cuối trong kết quả trả về show ra COMMAND là ps -e -opid,ppid,user,rss,command – chính là lệnh mà chúng ta dùng để chạy. Điều đó chứng tỏ, mỗi một command chính là một process !?

Ngoài ra lệnh ps cũng cho chúng ta thấy, mỗi một Process sẽ có một Process ID, và thuộc về một Process cha nào đó. Process ID là duy nhất đối với mỗi một process, tức là 2 process khác nhau chắc chắn phải có PID khác nhau. Ngoài ra Process ID là không thể thay đổi trong khi chạy process.

1. Làm sao hệ điều hành đánh số các Process ID?

Process ID được đánh số theo thứ tự tăng dần. Bắt đầu từ 0 và tăng lên cho tới khi gặp giá trị maximum. Giá trị maximum của Process ID là có thể cấu hình được tuỳ vào từng hệ thống.

Trên Linux bạn có thể xem và thay đổi giá trị mặc định của Process ID maximum bằng cách thay đổi file /proc/sys/kernel/pid_max

main.sh
1
2
3
4
5
6
# read current maximum value of process id
$> cat /proc/sys/kernel/pid_max
32768

# set maximum value for process id
$> echo 40000 > /proc/sys/kernel/pid_max

Khi process ID tăng đến giá trị maximum value, hệ điều hành (OS) sẽ quay trở lại đánh số từ một giá trị cụ thế (một số tài liệu nói giá trị này với Linux là 300, và với Mac OS là 100 – mình chưa biết cách để kiểm nghiệm điều này một cách an toàn)

UNIX cung cấp syscall getpid trả về Process ID của process hiện tại. Bạn có thể viết một chương trình C đơn gian để lấy ra process id với getpid. Tuy nhiên, bài viết này của tôi sẽ tập trung vào ngôn ngữ Ruby

Trong Ruby, muốn lấy Process ID của process hiện tai, bạn sử dụng Process.pid.

pid.rb
1
puts "Process pid: #{Process.pid}"

Dòng code trên gọi tới hàm puts – hàm này có tác dụng in một String ra màn hình. Chúng ta có thể manipulate các String trong Ruby thông qua các syntax #{}. Code ruby trong #{ } sẽ được thực hiện trước khi truyền cho String

irb.rb
1
2
3
4
5
$> irb

irb(main):001:0> puts "Example for String manipulate: 1 + 2 = #{1 + 2}"
Example for String manipulate: 1 + 2 = 3
=> nil

(Các file Ruby có extension là .rb. Để chạy một file ruby, bạn dùng lệnh ruby <file_name>. Không cần phải compile, rất đơn giản phải không)

2. Liệu có phải process nào cũng có Process cha?

Ở trên tôi đã nói rằng, mỗi một process đều thuộc về một Process cha nào đó. Nếu bạn suy nghĩ kỹ, bạn sẽ thấy có điều gì đó không ổn? À, thực ra điều này liên quan đến quá trình khởi động của UNIX. Khi UNIX được khởi động, nó sẽ start một process số 0 (với PID = 0) (process này là process của Kernel UNIX). Process 0 sẽ tạo ra cho nó một Process con, Process 1. Trong phần lớn hệ thống, Process 1 được đặt tên là init process, các process khác được tạo ra đều từ init process.

Hãy quay lại ví dụ về lệnh ps như ở phần đầu mục I. Bạn có thể để ý thấy PPID của dòng đầu tiên là 0. Đó chính là process đầu tiên của OS.

Vậy là process trong Unix thực chất được tổ chức dưới dạng cây. Mỗi một node trong cây đại diện cho một process trong Unix. Gốc chính là process 0, các con của một node chính là các process con của process ứng với node đó.

Trong Ruby, để lấy ra parent process id của một process, chúng ta sử dung Process.ppid

ppid.rb
1
2
# file test_ppid.rb
puts "Process id #{Process.pid}, parent process id #{Process.ppid}"

Cũng rõ ràng đấy chứ. Liệu tôi có quên gì nữa không nhỉ?

Vấn đề là làm sao một process có thể sinh ra một process con? À đừng lo, tôi sẽ nói kỹ về điều này ở phần 2

3. Process Resource

Ngoài ra lệnh ps của chúng ta còn cho thấy, mỗi Process đều có RSS khác nhau. RSS chính là bộ nhớ mà Process sử dụng. Các process khác nhau, có bộ nhớ khác nhau. Nói cách khác, không gian địa chỉ của các Process là riêng biệt. Nhớ thiết kế này mà các Process là độc lập với nhau. Nếu một Process bị chết, thì nó cũng không ảnh hưởng gì tới các Process khác.

Ngoài bộ nhớ, hệ điều hành còn cấp phát cho Process các tài nguyên khác đó là các file descriptor. Nhớ rằng trên UNIX, mọi thứ đều là file. Điều đó có nghĩa là, devide được coi như file, socket được coi như file, pipe cũng là file, và file cũng là file!!! Để cho đơn giản, chúng ta sẽ dùng Resource thay cho khái niệm file nói chung, và file đại diện cho khái niệm file thông thường.

Bất cứ khi nào bạn mở một Resource trong một process, resource đó sẽ được gán với một số file descriptor. File descriptor là không được chia sẽ giữa các process không liên quan. Các resource sẽ sống và tồn tại cùng với process mà nó thuộc về. Khi process chết đi, các resource gắn với nó sẽ được close và exit.

Mỗi một process sẽ có 3 files descriptor mặc định, bạn hẳn rất quen thuộc với chúng, đó chính là stdin, stdout và stderr. Các file descriptor được đánh số tăng dần từ 0 đến giá trị lớn nhất. Mỗi một process sẽ có một số giới hạn các file descriptor nó được quyền sử dụng.

II. forking

Ở phần I.2, chúng ta đã nói về process cha và process con, và đưa ra câu hỏi, làm sao một process có thể sinh ra các process khác.

UNIX cung cấp một công cụ tuyệt vời để làm điều đó. Bạn chắc đã đoán ra, đó chính là fork. Theo cá nhân tôi, fork có lẽ là một trong những chức năng tốt nhất của UNIX. Vì sao ư? Vì process con được tạo ra với fork có 2 đặc điểm:

  • process con được copy tất cả các memory từ process cha.
  • process con sẽ được kế thứa từ process cha các resource

Điều này có nghĩa là nếu trong process cha, bạn đã định nghĩa biến a, và gán giá trị cho nó, process con cũng có thể sử dụng biến đó.

Uhm… Không phải như thế sẽ dẫn đến tình trạng 2 process cùng thay đổi một biến hay sao, vả lại chẳng phải các process là độc lập về bộ nhớ.

À, tức là thế này, khi fork một process mới, bộ nhớ của process con và process cha vẫn là độc lập, nhưng hệ điều hành sẽ sử dụng cơ chế copy-on-wright (COW) để thực hiện việc đó. Tức là nếu process con không thay đổi các giá trị trong process cha, process con và process cha sẽ vẫn dùng chung bộ nhớ. Điều này làm cho các process con chỉ đọc, sẽ có memory rất nhỏ. Hay nói cách khác, UNIX cung cấp cho chúng ta một công cụ để chạy các multiprogram với một lượng resource vửa đủ.

Điều này đặc biết tốt khi bạn cần load các library. Process cha sẽ đảm nhiệm việc load các library khác nhau. Sau khi load xong, nó fork ra các process con, và thực hiện việc điều khiển các process con. Các process con nhờ cơ chế COW, không cần phải tốn thời gian load library nữa mà vẫn có thể truy xuất vào các library

Ngoài ra các process cha chia sẻ với process con các resource cũng dẫn đến một kỹ thuật khá thú vị: pre-forking – đặc biệt hiệu quả trong việc lập trình server.

Kỹ thuật này được mô tả như sau:

  • Main process khởi tạo một listening socket
  • Main process fork ra một list các children process. Chú ý các children process này cũng sẽ listen trên socket mà main process tạo ra. Nhưng việc dispatch các incomming connection tới các children process là được thực hiện trên kernel. Điều này làm cho việc dispatch các incomming connection là rất nhanh
  • Mỗi process sẽ accept các connection từ shared socket và xử lý chúng riêng biệt
  • Main process sẽ kiểm soát các children process. (cung cấp lệnh để tắt tất cả các children process, tạo một child process mới khi một child process bị crash…)

Kỹ thuật pre-forking được sử dụng rất nhiều. ví dụ: apache (httpd), nginx, celery, postgresql, rabbitmq, ….

Process trong Unix là một lĩnh vực rất thú vị, đặc biệt là trong lập trình hệ thống và lập trình server. Bài viết chỉ mới đề cập đến một vài kiến thức và kỹ thuật ban đầu với Process. Còn rất nhiều vấn đề chưa đề cập, như

  • Tương tác giữa các process (IPC)
  • Điều khiển các process
  • Orphaned, daemon, zoombie, process …

Hy vọng trong tương lai, mình sẽ có thể viết về các vấn đề này kỹ hơn.

Cai dat MAM server

1. Ca dat JDK.

– Download jdk40
– Cai dat JDK
[[email protected] Downloads]# rpm -ivh jdk-7u7-linux-x64.rpm
– Them bien moi truong
[[email protected] Downloads]# JAVA_HOME=/usr/java/jdk1.7.0_17
[[email protected] Downloads]# export JAVA_HOME
[[email protected] Downloads]# PATH=$JAVA_HOME/bin:$PATH
[[email protected] Downloads]# export PATH
[[email protected] Downloads]# vim /root/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

# User specific environment and startup programs
JAVA_HOME=/usr/java/jdk1.7.0_17/
export JAVA_HOME
PATH=$JAVA_HOME/bin:$PATH
export PATH
#PATH=$PATH:$HOME/bin
#export PATH
-Them bien moi truong sau khi khoi dong
Insert 2 line in /etc/profile

## export JAVA_HOME JDK/JRE ##
export JAVA_HOME=”/usr/java/latest”
## export JAVA_HOME JDK ##
export JAVA_HOME=”/usr/java/jdk1.7.0_45″
– Khoi dong lai may va kiem tra (cho ra ket qua la oke):
echo $JAVA_HOME
Chúng ta đã tải và lưu Apache Tomcat 7 vào thư mục /opt/, kế tiếp chúng ta sẽ tiến hành giải nén tập tin Apache Tomcat vừa tải được:

[[email protected] java]# cd /opt/

[[email protected] opt]# tar -xvf apache-tomcat-7.0.12.tar.gz

Kết thúc chúng giải nén được Apache Tomcat 7 nằm tại: /opt/apache-tomcat-7.0.12/

Bước 3: Cấu hình Apache Tomcat chạy như một dịch vụ

Để Apache Tomcat có thể dễ dàng Start, Stop, Restart và tự động chạy khi Centos khởi động nên chúng ta tạo đoạn init script như sau:

[[email protected] opt]# vi /etc/init.d/tomcat

#!/bin/bash

# description: Tomcat Start Stop Restart

# processname: tomcat

# chkconfig: 234 20 80

JAVA_HOME=/usr/java/jdk1.6.0_25

export JAVA_HOME

PATH=$JAVA_HOME/bin:$PATH

export PATH

CATALINA_HOME=/opt/apache-tomcat-7.0.12

case $1 in

start)

sh $CATALINA_HOME/bin/startup.sh

;;

stop)

sh $CATALINA_HOME/bin/shutdown.sh

;;

restart)

sh $CATALINA_HOME/bin/shutdown.sh

sleep 1

sh $CATALINA_HOME/bin/startup.sh

;;

esac

exit 0

Trong đoạn script trên biến CATALINA_HOME phải trỏ về thư mục chứa Apache Tomcat (/opt/apache-tomcat-7.0.12/)

Cấp quyền thực thi cho tập tin /etc/init.d/tomcat :

[[email protected] opt]# chmod +x /etc/init.d/tomcat

Tiếp tục sử dụng công cụ chkconfig để cấu hình cho Tomcat chạy lúc Centos khởi động ( ở đây ví dụ Tomcat tự động chạy ở runlevel 2,3,4) :

[[email protected] opt]# chkconfig –add tomcat

[[email protected] opt]# chkconfig –level 234 tomcat on

Kiểm tra lại:

[[email protected] opt]# chkconfig –list tomcat

tomcat 0:off 1:off 2:on 3:on 4:on 5:off 6:off

Bây giờ chúng ta sẽ tiến hành Start Apache Tomcat:

[[email protected] opt]# service tomcat start

Using CATALINA_BASE: /opt/apache-tomcat-7.0.12

Using CATALINA_HOME: /opt/apache-tomcat-7.0.12

Using CATALINA_TMPDIR: /opt/apache-tomcat-7.0.12/temp

Using JRE_HOME: /usr/java/jdk1.6.0_25

Using CLASSPATH: /opt/apache-tomcat-7.0.12/bin/bootstrap.jar:/opt/apache-tomcat-7.0.12/bin/tomcat-juli.jar

Chúng ta truy cập bằng HTTP vào cổng mặc định 8080 để kiếm tra ( ví dụ http://192.168.1.3:8080).

— Copy 2 file vao opt/apache…/webapp
— Vao Webapp— Xoa thu muc ROOT
— cd cd mam_service/WEB-INF/classes/
sua Url la dia chi web cua minh (ifconfig)

Compiling FFMPEG for CentOS 6.3 from source

  1. # Compiling FFMPEG for CentOS 6.3 from source
  2. # log of commands Sept 7th, 2012
  3. # I found this information very helpful:
  4. # http://cumulusclips.org/docs/install-ffmpeg-x264-on-centos/
  5. # http://ffmpeg.org/trac/ffmpeg/wiki/CentosCompilationGuide
  6. # You may have to add your own flavour of filters and codecs to the mix,
  7. # I just needed FFMPEG to transcode from H264 MP4 to H264 MP4 Mobile, WEBM and OGV.
  8. # first erase all ffmpeg related packages that you might have installed earlier:
  9. # (I left the rpm’s for libogg libvorbis libtheora installed – yum tried to remove too many dependencies to my liking)
  10. yum erase ffmpeg faac libfaac x264 libx264 libvpx
  11. # get some essential tools if needed (some are probably already installed)
  12. yum install gcc gcc-c++ automake autoconf libtool nasm git subversion nasm pkgconfig
  13. export LD_LIBRARY_PATH=/usr/local/lib/
  14. echo /usr/local/lib > /etc/ld.so.conf.d/custom-libs.conf
  15. ldconfig
  16. wget http://downloads.xvid.org/downloads/xvidcore-1.3.2.tar.gz
  17. tar zxf xvidcore-1.3.2.tar.gz
  18. cd xvidcore/build/generic
  19. ./configure –enable-shared
  20. make && make install
  21. ldconfig
  22. cd ../../../
  23. wget http://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Flame%2Ffiles%2F&ts=1346843156&use_mirror=dfn
  24. tar zxf lame-3.99.5.tar.gz
  25. cd lame-3.99.5
  26. ./configure –enable-shared
  27. make && make install
  28. ldconfig
  29. cd ..
  30. wget http://downloads.sourceforge.net/faac/faac-1.28.tar.gz
  31. tar xzf faac-1.28.tar.gz
  32. cd faac-1.28
  33. ./bootstrap
  34. ./configure –enable-shared
  35. make && make install
  36. ldconfig
  37. cd ..
  38. wget http://downloads.sourceforge.net/project/opencore-amr/opencore-amr/opencore-amr-0.1.3.tar.gz?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fopencore-amr%2Ffiles%2Fopencore-amr%2F&ts=1346843453&use_mirror=dfn
  39. tar xzf opencore-amr-0.1.3.tar.gz
  40. cd opencore-amr-0.1.3
  41. ./configure –enable-shared
  42. make && make install
  43. ldconfig
  44. cd ..
  45. wget http://downloads.xiph.org/releases/ogg/libogg-1.3.0.tar.gz
  46. tar xzf libogg-1.3.0.tar.gz
  47. cd libogg-1.3.0
  48. ./configure –enable-shared
  49. make && make install
  50. ldconfig
  51. cd ..
  52. wget http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.3.tar.gz
  53. tar xzf libvorbis-1.3.3.tar.gz
  54. cd libvorbis-1.3.3
  55. ./configure –enable-shared
  56. make && make install
  57. ldconfig
  58. cd ..
  59. wget http://downloads.xiph.org/releases/theora/libtheora-1.1.1.tar.bz2
  60. tar xjf libtheora-1.1.1.tar.bz2
  61. cd libtheora-1.1.1
  62. ./configure –enable-shared
  63. make && make install
  64. ldconfig
  65. cd ..
  66. // Yasm is an assembler used by x264 and FFmpeg.
  67. wget http://www.tortall.net/projects/yasm/releases/yasm-1.2.0.tar.gz
  68. tar xzvf yasm-1.2.0.tar.gz
  69. cd yasm-1.2.0
  70. ./configure
  71. make && make install
  72. ldconfig
  73. cd ..
  74. git clone git://git.videolan.org/x264.git
  75. cd x264
  76. ./configure –enable-static –enable-shared
  77. make && make install
  78. ldconfig
  79. cd ..
  80. wget http://downloads.sourceforge.net/opencore-amr/vo-aacenc-0.1.2.tar.gz
  81. tar xzvf vo-aacenc-0.1.2.tar.gz
  82. cd vo-aacenc-0.1.2
  83. ./configure –enable-shared
  84. make && make install
  85. ldconfig
  86. cd ..
  87. git clone http://git.chromium.org/webm/libvpx.git
  88. cd libvpx
  89. ./configure –enable-shared
  90. make && make install
  91. ldconfig
  92. cd ..
  93. wget http://zlib.net/zlib-1.2.7.tar.gz
  94. tar xzvf zlib-1.2.7.tar.gz
  95. cd zlib-1.2.7
  96. ./configure –enable-shared
  97. make && make install
  98. ldconfig
  99. cd ..
  100. git clone git://git.videolan.org/ffmpeg.git ffmpeg
  101. cd ffmpeg
  102. ./configure –enable-version3 –enable-libopencore-amrnb \
  103. –enable-libopencore-amrwb –enable-libvpx –enable-libfaac \
  104. –enable-libmp3lame –enable-libtheora –enable-libvorbis \
  105. –enable-libx264 –enable-libxvid –enable-gpl –enable-postproc \
  106. –enable-nonfree –enable-pthreads –enable-libvo-aacenc \
  107. –enable-postproc –enable-swscale –enable-avfilter \
  108. –enable-shared –enable-runtime-cpudetect  \
  109. –disable-stripping \
  110. –extra-cflags=’-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector –param=ssp-buffer-size=4 -m64 -mtune=generic -fPIC’
  111. make
  112. make install
  113. ldconfig

 

http://pastebin.com/mgu0YUKC#

Cài đặt Tomcat lên Centos 6.4 64bit

http://khanh.com.vn/post/2013/03/16/Install-Tomcat-7-on-Centos-63.aspx

 

Để có thể echo $JAVA_HOME.

Cần sửa như sau:

Post-Installation Setup

Add JAVA_HOME environment variable to /etc/profile file or $HOME/.bash_profile file

Java JDK and JRE latest version (/usr/java/latest)

## export JAVA_HOME JDK/JRE ##
export JAVA_HOME=”/usr/java/latest”

Java JDK and JRE absolute version (/usr/java/jdk1.7.0_40)

## export JAVA_HOME JDK ##
export JAVA_HOME=”/usr/java/jdk1.7.0_40″

 

Install Oracle Java 7u79/80 on Fedora 24/23, CentOS/RHEL 7.2/6.8/5.11

http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.30/bin/

https://mrhien.info/blog/cai-dat-apache-tomcat-7-tren-centos-5/

http://pastebin.com/mgu0YUKC

Bookmark online code

https://github.com/blamarche/openbookmark

http://gscripts.net/free-php-scripts/Other/online-bookmarks/details.html

http://www.hotscripts.com/category/scripts/php/scripts-programs/bookmark-management/