Showing posts with label Beginning Linux Programming. Show all posts

Resources and Limits




Monday, August 3, 2015

Logging

Log file là một file rất quan trong nên có cho mỗi chương trình để lưu lại tất cả thông tin về quá trình chạy của chương trình, từ đó có thể phân tích kiểm tra thông tin history, tìm kiếm lỗi nếu xảy ra, ...

1. syslog
 #include <syslog.h>  
 void syslog(int priority, const char *message, arguments...);  

syslog gửi log mesage đến file log hệ thống /var/log/messages và /var/log/debug bạn có thể dùng lệnh cat để xem log msg.

+ priority
Bitwire OR của level và facility value.

level:

Priority Level Description
LOG_EMERG An emergency situation
LOG_ALERT High-priority problem, such as database corruption
LOG_CRIT Critical error, such as hardware failure
LOG_ERR Errors
LOG_WARNING Warning
LOG_NOTICE Special conditions requiring attention
LOG_INFO Informational messages
LOG_DEBUG Debug messages

facility value:

Facility values Description
LOG_USER the message has come from a user application
LOG_LOCAL0 which can be assignedmeanings by the local administrator
... ...
LOG_LOCAL7

Tùy thuộc vào priority mà syslog sẽ có cách xử lý khác nhau đối với message, ví dụ với LOG_EMERG thì msg được gửi đến tất cả các user, LOG_ALERT thì msg được gửi mail đến administrator, LOG_DEBUG thì msg được bỏ qua, còn các trường hợp khác sẽ ghi vaog log file.

+ message
Message được syslog gửi đi.
+ arguments
Các đối số khác.
+ return

Ex:
syslog.c
   
 #include <syslog.h>  
 #include <stdio.h>  
 #include <stdlib.h>  
 int main()  
 {  
   FILE *f;  
   f = fopen("not_here","r");  
   if(!f)  
     syslog(LOG_ERR|LOG_USER,"oops hi hi ha ha - %m\n");  
   exit(0);  
 }  
   

Compile & Execute (root user):
 $ gcc syslog.c  
 $ su  
 # ./a.out  
 # cat /var/log/messages  
 Aug 2 11:24:00 localhost a.out: oops - No such file or directory  

2. openlog
 #include <syslog.h>  
 void closelog(void);  
 void openlog(const char *ident, int logopt, int facility);  
 int setlogmask(int maskpri);  

syslog không cho biết thông tin về user nào, chương trình nào tạo ra log msg, mà chỉ có một khuôn dạng log chung, vì thế trong nhiều trường hợp sẽ khó khăn để fixbug khi chương trình có lỗi. Chính vì thế cần có thêm các hàm để thay đổi hành vi của logger.

openlog mở logger ra để chỉnh sửa:
+ ident
Chuỗi string tùy ý bạn thêm vào dòng log msg.
+ logopt
log option của openlog:
 /*  
  * Option flags for openlog.  
  *  
  * LOG_ODELAY no longer does anything.  
  * LOG_NDELAY is the inverse of what it used to be.  
  */  
 #define     LOG_PID          0x01     /* log the pid with each message */  
 #define     LOG_CONS     0x02     /* log on the console if errors in sending */  
 #define     LOG_ODELAY     0x04     /* delay open until first syslog() (default) */  
 #define     LOG_NDELAY     0x08     /* don't delay open */  
 #define     LOG_NOWAIT     0x10     /* don't wait for console forks: DEPRECATED */  
 #define     LOG_PERROR     0x20     /* log to stderr as well */  

+ facility
Tương tự như trên syslog.

setlogmask điều khiển priority level của syslog:
+ maskpri
Set môt priority với LOG_MASK(priority) hoặc một dải priority với LOG_UPTO(priority)

Ex:
logmask.c
 #include <syslog.h>  
 #include <stdio.h>  
 #include <unistd.h>  
 #include <stdlib.h>  
   
 int main()  
 {  
   int logmask;  
   openlog("logmask", LOG_PID|LOG_CONS, LOG_USER);  
   
   /*  
    * ghi ra /var/log/messages  
    *  
    */  
   syslog(LOG_INFO,"informative message, pid = %d", getpid());  
   
   /*  
    * ghi ra /var/log/debug  
    *  
    */  
   syslog(LOG_DEBUG,"debug message, should appear");  
   
   /*  
    * Bỏ qua tất cả các msg có priority < LOG_NOTICE  
    *  
    */  
   logmask = setlogmask(LOG_UPTO(LOG_NOTICE));  
   syslog(LOG_DEBUG,"debug message, should not appear");  
   
   exit(0);  
 }  
   

Compile & Execute:
 $ gcc logmask.c   
 $ su  
 # ./a.out   
 # cat /var/log/messages  
 Aug 2 22:14:29 localhost logmask[4676]: informative message, pid = 4676  
   



Temporary Files

Trong lúc chương trình chạy, đôi lúc chương trình cần có một file tạm để ghi các thông tin tam thời vào, Unix/Linux cung cấp một số hàm để thực hiện điều đó:

 #include <stdio.h>  
 char *tmpnam(char *s);  
 FILE *tmpfile(void);

tmpnam tạo ta một file tạm:
+ s
File trả về được ghi vào đây, s có độ dài ít nhất bằng L_tmpnam.
+ return
Trả về một file có tên không trình với bất kỳ tên nào đã tồn tại.


tmpfile mở file tạm được trả về từ tmpnam, hàm này tương đương với fopen w+
+ return
Trả về file stream của file tạm.

Ex:
tmpfile.c
 #include <stdio.h>  
 #include <stdlib.h>  
 int main()  
 {  
   char tmpname[L_tmpnam];  
   char *filename;  
   FILE *tmpfp;  
   filename = tmpnam(tmpname);  
   printf("Temporary file name is: %s \n", filename); //filename == tmpname  
   tmpfp = tmpfile();  
   if(tmpfp)  
     printf("Opened a temporary file OK\n");  
   else  
     perror("tmpfile");  
   exit(0);  
 }  
   

Compile & Execute:
 $ gcc tmpname.c   
 $ ./a.out   
 Temporary file name is: /tmp/fileaNvouf   
 Opened a temporary file OK  
   


Sunday, August 2, 2015

Host Information

Trong Shell bạn dùng lệnh uname để lấy thông tin về host của mình đang sử dụng:

 $ uname  
 Linux  
 $ uname -a  
 Linux localhost.localdomain 3.18.6-100.fc20.x86_64 #1 SMP Fri Feb 6 22:55:01 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux  
 $   
 $ uname -i  
 x86_64  
   

Unix/Linux cung cấp các API:
 #include <unistd.h>  
 int gethostname(char *name, size_t namelen);  
+ name
Bufer, tên của host được trả về tại đây
+ namelen
Độc dài của buffer
+ return
Trả về 0 nếu thành công.

 #include <sys/utsname.h>  
 int uname(struct utsname *name);  

struct utsname:
 struct utsname {  
         char sysname[];  /* Operating system name (e.g., "Linux") */  
         char nodename[];  /* Name within "some implementation-defined  
                    network" */  
         char release[];  /* Operating system release (e.g., "2.6.28") */  
         char version[];  /* Operating system version */  
         char machine[];  /* Hardware identifier */  
       #ifdef _GNU_SOURCE  
         char domainname[]; /* NIS or YP domain name */  
       #endif  
       };  

+ name
Struct lưu trữ host information.
+ return
Trả về số > 0 nếu thành công; -1 nếu lỗi, kèm mã lỗi errno.

Ex:
hostget.c
 #include <sys/utsname.h>  
 #include <unistd.h>  
 #include <stdio.h>  
 #include <stdlib.h>  
   
 int main()  
 {  
   char computer[256];  
   struct utsname uts;  
   if(gethostname(computer, 255) != 0 || uname(&uts) < 0) {  
     fprintf(stderr, "Could not get host information\n");  
     exit(1);  
   }  
   printf("Computer host name is %s\n", computer);  
   printf("System is %s on %s hardware\n", uts.sysname, uts.machine);  
   printf("Nodename is %s\n", uts.nodename);  
   printf("Version is %s, %s\n", uts.release, uts.version);  
   exit(0);  
 }  
   

Compile & Execute:
 $ gcc hostget.c   
 $ ./a.out   
 Computer host name is localhost.localdomain  
 System is Linux on x86_64 hardware  
 Nodename is localhost.localdomain  
 Version is 3.18.6-100.fc20.x86_64, #1 SMP Fri Feb 6 22:55:01 UTC 2015  


User Information

Bài viết liên quan:
+ Users and Groups

Một OS bao giờ cũng tạo ra các User và gom nhiều user có điểm chung lại với nhau thành Group, các user và group được định danh theo con số duy nhất gọi là UID (User IDentifier) và GID (Group IDentifier). Unix/Linux cung cấp các API để giúp chưng trình lấy được thông tin về User và Group mà nó thuộc về.

1. User and Groups 
 #include <sys/types.h>  
 #include <unistd.h>  
 uid_t getuid(void); //trả về UID
 gid_t getgid(void); //trả về GID
 int setuid(uid_t uid);
 int setgid(gid_t gid);
 char *getlogin(void); //trả về login name của user  

Các thông tin trên được lưu trong /etc/passwd có dạng:
 account:password:UID:GID:GECOS:directory:shell  

account is the user name
password is the user password
UID is the numerical user ID
GID is the numerical primary group ID for the user
GECOS is an optional field used for informational purposes; usually it contains the full user name
directory is the user's $HOME directory
shell is the user command interpreter (defaults to /bin/sh)

Ex:
 $ cat /etc/passwd | grep ninhld  
 ninhld:x:1000:1000:ninhld:/home/ninhld:/bin/bash  

2. Password Database
 #include <sys/types.h>  
 #include <pwd.h>  
 struct passwd *getpwuid(uid_t uid);  
 struct passwd *getpwnam(const char *name);  

struct passwd:

passwd Member Description
char *pw_name The user’s login name
uid_t pw_uid The UID number
gid_t pw_gid The GID number
char *pw_dir The user’s home directory
char *pw_gecos The user’s full name
char *pw_shell The user’s default shell

Thông tin về Password Database được lưu trong /etc/passwd

Để lấy tât cả thông tin trong Password Database:
 #include <pwd.h>  
 #include <sys/types.h>  
 void setpwent(void);           //trở về đầu database
 struct passwd *getpwent(void); //sacn tất cả entry, khi không còn thì trả về NULL
 void endpwent(void);           //đóng database khi scan xong 

Ex1:
user.c
 #include <sys/types.h>  
 #include <pwd.h>  
 #include <stdio.h>  
 #include <unistd.h>  
 #include <stdlib.h>  
   
 int main()  
 {  
   uid_t uid;  
   gid_t gid;  
   struct passwd *pw;  
   uid = getuid();  
   gid = getgid();  
   printf("User is %s\n", getlogin());  
   printf("User IDs: uid=%d, gid=%d\n", uid, gid);  
   pw = getpwuid(uid);  
   printf("UID passwd entry:\n name=%s, uid=%d, gid=%d, home=%s, shell=%s\n",  
       pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_dir, pw->pw_shell);  
   pw = getpwnam("root");  
   printf("root passwd entry:\n");  
   printf("name=%s, uid=%d, gid=%d, home=%s, shell=%s\n",  
       pw->pw_name, pw->pw_uid, pw->pw_gid, pw->pw_dir, pw->pw_shell);  
   exit(0);  
 }  
   

Compile & Execute:
 $ gcc user.c   
 $ ./a.out   
 User is ninhld  
 User IDs: uid=1000, gid=1000  
 UID passwd entry:  
  name=ninhld, uid=1000, gid=1000, home=/home/ninhld, shell=/bin/bash  
 root passwd entry:  
 name=root, uid=0, gid=0, home=/root, shell=/bin/bash  


Ex2:
getpwent.c
 /*  
  * This program loops, reading a login name from standard  
  * input and checking to see if it is a valid name. If it  
  * is not valid, the entire contents of the name in the  
  * password database are printed.  
  */  
 #include <stdio.h>  
 #include <sys/types.h>  
 #include <pwd.h>  
   
 void main()  
 {  
   struct passwd *pw;  
   
   setpwent( );  
   while( ( pw=getpwent( ) ) != ( struct passwd * )0 )  
     printf( "%s\n", pw->pw_name );  
   endpwent();  
 }  
   

Compile & Execute:
 $ gcc getpwent.c   
 $ ./a.out   
 root  
 bin  
 daemon  
 adm  
 lp  
 sync  
 shutdown  
 halt  
 mail  
 operator  
 games  
 ftp  
 nobody  
 avahi-autoipd  
 dbus  
 polkitd  
 usbmuxd  
 rtkit  
 chrony  
 tss  
 unbound  
 openvpn  
 avahi  
 pulse  
 lightdm  
 nm-openconnect  
 colord  
 sshd  
 tcpdump  
 ninhld  
 abrt  
 rpc  
 rpcuser  
 nfsnobody  
 stap-server  
   





Time and Date

1. time
Unix/Linux cung cấp thư viện time.h bao gồm các cấu trúc và hàm để xác định thời gian. Chúng thường được dùng để làm bộ timer, đo tốc độ của một đoạn xử lý logic, ...Thời gian trong Unix/Linux được lấy mốc là 00:00:00 (hh:mm:ss) 01-01-1970 UTC.

 #include <time.h>  
 time_t time(time_t *tloc);  

Hàm time lấy thời gian hiện tại.
+ tloc
Thời gian hiện tại trả về được lưu vào tloc nếu tloc không NULL.
+ return
Trả về thời gian hiện tại lưu trong time_t tính bằng giây tính từ thời điểm bắt đầu 00:00:00 (hh:mm:ss) 01-01-1970 UTC.

Ex:
envtime.c
 #include <time.h>  
 #include <stdio.h>  
 #include <unistd.h>  
 #include <stdlib.h>  
   
 int main()  
 {  
   int i;  
   time_t the_time, timmer;  
   for(i = 1; i <= 5; i++) {  
     the_time = time(&timmer);  
     printf("The time is %ld\n", the_time); // the_time == timmer  
     sleep(1);  
   }  
   exit(0);  
 }  
   

Execute:
 $ gcc envtime.c   
 $ ./a.out   
 The time is 1438358154  
 The time is 1438358155  
 The time is 1438358156  
 The time is 1438358157  
 The time is 1438358158  
   

2. gmtime
 #include <time.h>  
 struct tm *gmtime(const time_t timeval);  

struct tm:

Ex:
gmtime.c
 #include <time.h>  
 #include <stdio.h>  
 #include <stdlib.h>  
 int main()  
 {  
   struct tm *tm_ptr;  
   time_t the_time;  
   (void) time(&the_time);  
   
   tm_ptr = gmtime(&the_time);  
   printf("Raw time is %ld\n", the_time);  
   printf("gmtime gives:\n");  
   printf("date: %02d/%02d/%02d\n",  
       tm_ptr->tm_year, tm_ptr->tm_mon+1, tm_ptr->tm_mday);  
   printf("time: %02d:%02d:%02d\n",  
       tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec);  
   exit(0);  
 }  
   

Execute:
 $ gcc gmtime.c   
 $ ./a.out   
 Raw time is 1438358295  
 gmtime gives:  
 date: 115/07/31  
 time: 15:58:15  
   

3. ctime
 #include <time.h>  
 char *asctime(const struct tm *timeptr);  
 char *ctime(const time_t *timeval);  

Ex:
ctime.c
 #include <time.h>  
 #include <stdio.h>  
 #include <stdlib.h>  
 int main()  
 {  
   time_t timeval;  
   (void)time(&timeval);  
   printf("The date is: %s", ctime(&timeval));  
   exit(0);  
 }  
   

 $ gcc ctime.c   
 $ ./a.out   
 The date is: Fri Jul 31 23:00:27 2015  

4. localtime
 #include <time.h>  
 struct tm *localtime(const time_t *timeval);  

Ex:
localtime.c
 /* localtime example */  
 #include <stdio.h>   /* puts, printf */  
 #include <time.h>    /* time_t, struct tm, time, localtime */  
   
 int main ()  
 {  
  time_t rawtime;  
  struct tm * timeinfo;  
   
  time (&rawtime);  
  timeinfo = localtime (&rawtime);  
  printf ("Current local time and date: %s", asctime(timeinfo));  
   
  return 0;  
 }  

Execute:
 $ gcc localtime.c  
 $ ./a.out  
 Current local time and date: Fri Jul 31 16:11:47 2015  

5. gettimeofday
 #include <sys/time.h>  
 int gettimeofday(struct timeval *tv, struct timezone *tz);  
 int settimeofday(const struct timeval *tv, const struct timezone *tz);  

 struct timeval {  
   time_t   tv_sec;   /* seconds */  
   suseconds_t tv_usec;  /* microseconds */  
 };  
   
 struct timezone {  
   int tz_minuteswest;   /* minutes west of Greenwich */  
   int tz_dsttime;     /* type of DST correction */  
 };  

Ex:
gettimeofday.c
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <sys/time.h>  
   
 int main()  
 {  
   long int cycle = 2000000;//us ~ 2s  
   struct timeval tv, tv2;  
   
   gettimeofday(&tv,NULL);  
   while(1){  
     gettimeofday(&tv2,NULL);  
     if(tv2.tv_sec * 1000000 + tv2.tv_usec >= tv.tv_sec * 1000000 + tv.tv_usec + cycle){  
       printf("Timer is starting ... \n");  
       break;  
     }  
   }  
   
   return 0;  
 }  
   

Saturday, August 1, 2015

Environment Variables

1. Get and Set environment variables
Thư viện stdlib.h cung cấp các hàm để chương trình tương tác với các biến môi trường bên ngoài.

 #include <stdlib.h>  
 char *getenv(const char *name);  
 int putenv(const char *string);  

getenv lấy giá trị của biến môi trường.
+ name
Tên của biến môi trường
+ return
Trả về NULL nếu name không tồn tại.
Trả về string rỗng nếu name tồn tại nhưng không có giá trị.
Trả về giá trị của name nếu name tồn tại và có giá trị.

putenv gán giá trị cho biến môi trường.
+ string
Chuỗi gán biến môi trường và giá trị của nó.
+ return
Trả về -1 nếu coa lỗi.

Ex:
environ.c
 #include <stdio.h>  
 #include <stdlib.h>  
   
 int main ()  
 {  
   char *tmp;  
   
   tmp = getenv("PATH");  
   if(tmp)  
     printf("PATH : %s\n", tmp);  
   
   tmp = getenv("HOME");  
   if(tmp)  
     printf("HOME : %s\n", tmp);  
   
   tmp = getenv("ROOT");  
   if(tmp){  
     printf("ROOT : %s\n", tmp);  
   } else{  
     char *root = "ROOT=/root";  
     putenv(root);  
     printf("set ROOT : %s\n", getenv("ROOT"));  
   }  
   
   return(0);  
 }  
   

Compile & Execute:
 $ gcc environ.c   
 $ ./a.out   
 PATH : /usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin  
 HOME : /home/ninhld  
 set ROOT : /root  
   


2. The environ Variable
 #include <stdlib.h>  
 extern char **environ;  

environ là mảng chứa tất cả các biến môi trường và giá trị của chúng.

Ex:
showenv.c
 #include <stdlib.h>  
 #include <stdio.h>  
 extern char **environ;  
 int main()  
 {  
   char **env = environ;  
   while(*env) {  
     printf("%s\n",*env);  
     env++;  
   }  
   exit(0);  
 }  
   

Compile & Execute:
 $ gcc showenv.c   
 $ ./a.out   
 XDG_VTNR=1  
 MATE_DESKTOP_SESSION_ID=this-is-deprecated  
 SSH_AGENT_PID=1418  
 XDG_SESSION_ID=1  
 HOSTNAME=localhost.localdomain  
 XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/ninhld  
 IMSETTINGS_INTEGRATE_DESKTOP=yes  
 GPG_AGENT_INFO=/home/ninhld/.cache/keyring-PhSdLU/gpg:0:1  
 TERM=xterm-256color  
 SHELL=/bin/bash  
 HISTSIZE=1000  
 HELLO=hello  
 WINDOWID=67108895  
 OLDPWD=/home/ninhld  
 GNOME_KEYRING_CONTROL=/home/ninhld/.cache/keyring-PhSdLU  
 QTDIR=/usr/lib64/qt-3.3  
 QTINC=/usr/lib64/qt-3.3/include  
 IMSETTINGS_MODULE=IBus  
 QT_GRAPHICSSYSTEM_CHECKED=1  
 USER=ninhld  
 ...

- Copyright © Lập trình hệ thống nhúng Linux . Powered by Luong Duy Ninh -