2008년 02월 25일
관련글 1 2 3글 길게 쓰기 좀 그래서 대충 그냥 넘어가자.. 1. Two levels of AutoFS tracing are available: | Detailed (level 3) | | | | Includes traces of all AutoFS requests and replies, mountattempts, timeouts, and unmount attempts. You can start level 3tracing while AutoFS is running. | | Basic (level 1) | | Includes traces of all AutoFS requests and replies.You must restart AutoFS to start level 1 tracing. |
StoppingAutoFS Detailed Tracing |  |
To stop detailed tracing, issue the same commands (that startlevel 3 tracing) to send the SIGUSR2 signal to automountd. The SIGUSR2 signal is a toggle that turns tracing on or offdepending on its current state. If you have basic (level 1) tracing turned on when you sendthe SIGUSR2 signal to automountd, the SIGUSR2 signal turns tracing off. StartingAutoFS Basic Tracing |  |
To start basic (level 1) tracing, perform the following steps: Log on as root to the NFS client. Add -T to the AUTOMOUNTD_OPTIONS variable in the /etc/rc.config.d/nfsconf file, as in the following example: This change puts AutoFS basic tracing messages into the /var/adm/automount.log file. To get a list of all the automounted directorieson the client, issue the following command: for FS in $(grep autofs /etc/mnttab | awk ‘{print $2}’) do grep ‘nfs’ /etc/mnttab | awk ‘{print $2}’ | grep ^${FS} done |
For every automounted directory listed by the grep command, issue the following command to determinewhether the directory is currently in use: /usr/sbin/fuser -cu local_mount_point |
This command lists the process IDs and user names of all theusers using the mounted directory. Warn the users to cd out of the directory, and kill the processes that areusing the directory, or wait until the processes terminate. You canissue the following command to kill all the processes using the mounteddirectory: /usr/sbin/fuser -ck local_mount_point |
To kill AutoFS, issue the following command: /sbin/init.d/nfs.client stop |
 |  |  |  |  | WARNING! Do not kill the automountd daemon with the kill command becauseit does not die gracefully. Moreover, it does not unmount AutoFSmount points before it dies. Use the nfs.clientstop script to make sure automountd diescleanly. |  |  |  |  |
To start AutoFS with tracing enabled, issue thefollowing command: /abin/init.d/nfs.client start |
StoppingAutoFS Basic Tracing |  |
To stop basic tracing, kill AutoFS and restart it (as describedin the preceding section) by removing -T from the AUTOMOUNTD_OPTIONS variable. AutoFSTracing Output |  |
The most interesting events to users are the tracing outputwhen mounting and unmounting of file systems occur. MountEvent Tracing OutputThe general format of a mount event trace is as follows:MOUNTREQUEST: <time stamp> <mountinformation> <other tracing> ... <other tracing> MOUNT REPLY: <status>=mount status The <mount information> trace has the following format: name=<key>[<subdirectory>]<map>= map name <opts>=mount options <path>=mountpath <other tracing> where: <key> = the key value from the map <subdirectory> = subdirectory (may be blank) <map> = name of the map <opts> = mount options <path> = mount path <other tracing> = other trace information The mount status in the mount reply contains 0 if the mountis successful; it has a non-zero value when the mount is not successful. The following is an example of a typical mount trace:  |
May 13 18:45:09 t5 MOUNT REQUEST: Tue May 13 18:45:09 2003 May 13 18:45:09 t5 name=nfs127[/tmp] map=auto.indirect opts= path=/n2ktmp_8264/nfs127/tmp direct=1 May 13 18:45:09 t5 PUSH /etc/auto.indirect May 13 18:45:09 t5 POP /etc/auto.indirect May 13 18:45:09 t5 mapline: hpnfs127:/ /tmp hpnfs127:/tmp May 13 18:45:09 t5 do_mount1: May 13 18:45:09 t5 (nfs,nfs) /n2ktmp_8264/nfs127/tmp hpnfs127:/tmp penalty=0 May 13 18:45:09 t5 nfsmount: input: hpnfs127[other] May 13 18:45:09 t5 nfsmount: standard mount on /n2ktmp_8264/nfs127/tmp : May 13 18:45:09 t5 hpnfs127:/tmp May 13 18:45:09 t5 nfsmount: v3=1[0],v2=0[0] => v3. May 13 18:45:09 t5 nfsmount: Get mount version: request vers=3 min=3 May 13 18:45:09 t5 nfsmount: mount version=3 May 13 18:45:09 t5 Port numbers are 937, 937 May 13 18:45:09 t5 Port match May 13 18:45:09 t5 mount hpnfs127:/tmp /n2ktmp_8264/nfs127/tmp() May 13 18:45:09 t5 nfs_args: hpnfs127, , 0x2004060, 0, 0, 0, 0, 0, 0, 0, 0, May 13 18:45:09 t5 args_temp: hpnfs127, , 0x3004060, 0, 0, 0, 0, 0, 0, 0, 0, hpnfs127:/tmp May 13 18:45:09 t5 mount hpnfs127:/tmp dev=44000004 rdev=0 OK May 13 18:45:09 t5 MOUNT REPLY: status=0, AUTOFS_DONE |
 |
UnmountEvent Tracing OutputThe general format of an unmount event trace is as follows: UNMOUNT REQUEST: <time stamp> <other tracing> ... <other tracing> UNMOUNT REPLY: <status>=unmount status The unmount status in the unmount reply contains 0 if the unmountis successful; it has a non-zero value when the unmount is not successful. The following is an example of a typical unmount trace event: May 13 18:46:27 t1 UNMOUNT REQUEST: Tue May 13 18:46:27 2003 May 13 18:46:27 t1 dev=44000004 rdev=0 direct May 13 18:46:27 t1 ping: hpnfs127 request vers=3 min=2 May 13 18:46:27 t1 pingnfs OK: nfs version=3 May 13 18:46:27 t1 nfsunmount: umount /n2ktmp_8264/nfs127/tmp May 13 18:46:27 t1 Port numbers are 937, 937 May 13 18:46:27 t1 Port match May 13 18:46:27 t1 nfsunmount: umount /n2ktmp_8264/nfs127/tmp OK May 13 18:46:27 t1 unmount /n2ktmp_8264/nfs127/tmp OK May 13 18:46:27 t1 UNMOUNT REPLY: status=0
2.
AutoFSLogging |  |
AutoFS logs messages through /usr/sbin/syslogd. By default, syslogd writes messages to the file /var/adm/syslog/syslog.log. See the syslogd (1M) manpage for more information. Log in as root to the NFS client. Enter the following command to get a list of allthe automounted directories on the client: for FS in $(grep autofs /etc/mnttab | awk ‘{print $2}’) do grep ‘nfs’ /etc/mnttab | awk ‘{print $2}’ | grep ^${FS} done |
For every automounted directory listed by the grep command, enter the following command to determinewhether the directory is currently in use: /usr/sbin/fuser -cu local_mount_point |
This command lists the process IDs and user names of everyone usingthe mounted directory. Warn any users to cd out of the directory, and kill any processes that areusing the directory, or wait until the processes terminate. You canenter the following command to kill all the processes using the mounteddirectory: /usr/sbin/fuser -ck local_mount_point |
Enter the following commands to kill the AutoFS:  |  |  |  |  | CAUTION: Do not kill the automountd daemonwith the kill command. It does notunmount AutoFS mount points before it dies. Use the nfs.client stop script to ensurethat automountd dies. |  |  |  |  |
Add -v to AUTOMOUNTD_OPTIONS variable in the /etc/rc.config.d/nfsconf file, as in the following example: AUTOMOUNTD_OPTIONS = “-v” This change will enable AutoFS logging. Enter the following commands to start AutoFS: /sbin/init.d/nfs.client start
To stop AutoFS logging, kill AutoFS and restart it after removing “-v” option from AUTOMOUNTD_OPTIONS. AutoFSTracing |  |
Two levels of AutoFS tracing are available: | Detailed (level 3) | | | | Includes traces of all AutoFS requests and replies, mountattempts, timeouts, and unmount attempts. You can start level 3tracing while AutoFS is running. | | Basic (level 1) | | Includes traces of all AutoFS requests and replies.You must restart AutoFS to start level 1 tracing. |
ToStart AutoFS Basic TracingLog in as root to the NFS client. Add -T to the AUTOMOUNTD_OPTIONS variable in the /etc/rc.config.d/nfsconf file, as in the following example: This change puts AutoFS basic tracing messages into the file /var/adm/automount.log. Enter the following command to get a list of allthe automounted directories on the client: for FS in $(grep autofs /etc/mnttab | awk ‘{print $2}’) |
grep ‘nfs’ /etc/mnttab | awk ‘{print $2}’ | grep ^${FS} |
For every automounted directory listed by the grep command, enter the following command to determinewhether the directory is currently in use: /usr/sbin/fuser -cu local_mount_point |
This command lists the process IDs and user names of everyone usingthe mounted directory. Warn any users to cd out of the directory, and kill any processes that areusing the directory, or wait until the processes terminate. You canenter the following command to kill all the processes using the mounteddirectory: /usr/sbin/fuser -ck local_mount_point |
Enter the following command to kill the AutoFS:  |  |  |  |  | CAUTION: Do not kill the automountd daemon with the kill command.It does not unmount AutoFS mount points before it dies. Use the nfs.client stop script to ensure that automountd dies. |  |  |  |  |
Enter the following command to start AutoFS withtracing enabled: /abin/init.d/autofs start |
ToStop AutoFS Basic Tracing To stop AutoFS tracing, kill AutoFS and restart it only withremoving -T from AUTOMOUNTD_OPTIONS. The most interesting events to the users are the tracing outputwhen mounting and unmounting of file systems occur. MountEvent Tracing OutputThe general format of a mount event trace is:MOUNT REQUEST: <time stamp> <mountinformation> <other tracing> ... <other tracing> MOUNT REPLY: <status>=mount statusThe <mount information> trace has the following format (all on oneline): name=<key>[<subdirectory>]<map>= map name <opts>=mount options <path>=mountpath <other tracing> where: <key> = the key value from the map <subdirectory> = subdirectory (may be blank) <map> = name of map <opts> = mount options <path> = mount path <other tracing> = other trace information The mount status in the mount reply contains 0 if the mount is successful,it has non-zero value when the mount is not successful. The following is an example of a typical mount trace:May 1318:45:09 t5 MOUNT REQUEST: Tue May 1318:45:09 2003May 13 18:45:09 t5 name=nfs127[/tmp] map=auto.indirectopts=path=/n2ktmp_8264/nfs127/tmp direct=1May 13 18:45:09 t5 PUSH/etc/auto.indirectMay 13 18:45:09 t5 POP /etc/auto.indirectMay13 18:45:09 t5 mapline: hpnfs127:/ /tmp hpnfs127:/tmpMay 13 18:45:09 t5 do_mount1:May 13 18:45:09t5 (nfs,nfs) /n2ktmp_8264/nfs127/tmp hpnfs127:/tmp penalty=0May 13 18:45:09 t5 nfsmount: input: hpnfs127[other]May13 18:45:09 t5 nfsmount: standard mount on/n2ktmp_8264/nfs127/tmp:May 13 18:45:09 t5 hpnfs127:/tmpMay13 18:45:09 t5 nfsmount: v3=1[0],v2=0[0] => v3.May13 18:45:09 t5 nfsmount: Get mount version: request vers=3min=3May13 18:45:09 t5 nfsmount: mount version=3May 13 18:45:09 t5 Port numbers are 937, 937May 13 18:45:09t5 Port matchMay 13 18:45:09 t5 mount hpnfs127:/tmp /n2ktmp_8264/nfs127/tmp()May 13 18:45:09 t5 nfs_args: hpnfs127, , 0x2004060, 0, 0, 0, 0,0, 0, 0, 0,May13 18:45:09 t5 args_temp: hpnfs127, , 0x3004060, 0, 0, 0,0,0, 0, 0, 0, hpnfs127:/tmpMay 13 18:45:09 t5 mount hpnfs127:/tmpdev=44000004 rdev=0 OKMay 13 18:45:09 t5 MOUNTREPLY: status=0, AUTOFS_DONE UnmountEvent Tracing OutputThe general format of an unmount event trace is: UNMOUNT REQUEST: <time stamp> <other tracing> ... <other tracing> UNMOUNT REPLY: <status>=unmount status The unmount status in the unmount reply contains 0 if the unmountis successful, it has a non-zero value when the unmount is not successful. The following is an example of a typical unmount trace event: May 13 18:46:27 t1 UNMOUNT REQUEST: Tue May 13 18:46:27 2003 May 13 18:46:27 t1 dev=44000004 rdev=0 direct May 13 18:46:27 t1 ping: hpnfs127 request vers=3 min=2 May 13 18:46:27 t1 pingnfs OK: nfs version=3 May 13 18:46:27 t1 nfsunmount: umount /n2ktmp_8264/nfs127/tmp May 13 18:46:27 t1 Port numbers are 937, 937 May 13 18:46:27 t1 Port match May 13 18:46:27 t1 nfsunmount: umount /n2ktmp_8264/nfs127/tmp OK May 13 18:46:27 t1 unmount /n2ktmp_8264/nfs127/tmp OK May 13 18:46:27 t1 UNMOUNT REPLY: status=0
|
Loggingfor the Other NFS Services |  |
You can configure logging for the following NFS services: Logging is not available for the rpc.quotad daemon. Each message logged by these daemons can be identified bythe date, time, host name, process ID, and name of the functionthat generated the message. You can direct logging messages fromall these NFS services to the same file. ToControl the Size of Log FilesLog files grow without bound, using up disk space. You mightwant to create a cron job to truncate your log files regularly. Followingis an example crontab entry that empties the log file at 1:00 AM every Monday,Wednesday, and Friday: 0 1 * * 1,3,5 cat /dev/null > log_file |
For more information, type man 1M cron or man 1 crontab at the HP-UX prompt. ToConfigure Logging for the Other NFS ServicesAdd the -l logfile option to the lines in /etc/inetd.conf for the services you want to log. In the followingexample, logging is turned on for rpc.rexd and rpc.rstatd: rpc stream tcp nowait root /usr/sbin/rpc.rexd 100017 1 \ rpc.rexd -l /var/adm/rpc.log rpc dgram udp wait root /usr/lib/netsvc/rstat/rpc.rstatd \ 100001 1-3 rpc.rstatd -l /var/adm/rpc.log |
Enter the following command to restart inetd:
If you do not specify a log file for the other NFS services(with the -l option), they do not log any messages. The NFSservices can all share the same log file. For more information, see rexd(1M),rstatd(1M), rusersd(1M), rwalld(1M) ,and sprayd(1M). LoggingWith nettl and netfmt |  |
Enter the following command to make sure nettl is running: /usr/bin/ps -ef | grep nettl |
If nettl is not running, enter the following command tostart it: Enter the following command to start logging: /usr/sbin/nettl -l i w e d -e all |
The logging classes are specified following the -l option. They are i (informational), w (warning), e (error), and d (disaster). Disaster logging is always on. Youcannot turn it off. Information logging (i) fills up your log file faster than the otherclasses, so you might want to leave it off. Recreate the event you want to log. Enter the following command to turn logging off: /usr/sbin/nettl -l d -e all |
This command changes the logging class back to disaster onlyfor all subsystems. Enter the following command to format the binarylog file: /usr/sbin/netfmt -lN -f /var/adm/nettl.LOG00 > formatted_file |
where formatted_file is the name of the file where you want the formattedoutput from netfmt. The default log file, /var/adm/nettl.LOGnn, is specified in the nettl configuration file, /etc/nettlgen.conf. If the file /var/adm/nettl.LOG00 does not exist on your system, the default logfile may have been changed in /etc/nettlgen.conf.
For more information, see nettl(1M) and netfmt(1M). TracingWith nettl and netfmt |  |
Enter the following command to make sure nettl is running: /usr/bin/ps -ef | grep nettl |
If nettl is not running, enter the following command tostart it: Enter the following command to start tracing: /usr/sbin/nettl -tn pduin pduout loopback -e all -s 1024 \ -f tracefile |
Recreate the event you want to trace. Enter the following command to turn tracing off: /usr/sbin/nettl -tf -e all |
Create the following filter file for netfmt: filter ip_saddr remote_host_IP_address filter ip_daddr remote_host_IP_address filter rpcprogram nfs filter rpcprogram nlockmgr filter rpcprogram llockmgr filter rpcprogram status filter rpcprogram mount filter rpcprogram rpcbind |
remote_host_IP_address is the IP address of the host with which yourhost was communicating when the event you want to trace occurred. Enter the following command to format the binarytrace file: /usr/sbin/netfmt -c filter_file -lN -f tracefile.TRC0 > formatted_file |
where tracefile is the name of the file you specified when you startedtracing, and formatted_file is the name of the file where you want the formattedoutput from netfmt.
For more information, type man 1M nettl or man 1M netfmt.
3.
시그널의 특징 : 시그널은 대기열이 없다시그널은 한 프로세스에 대해서 발생하는 시그널을 큐잉 하지 못한다(대부분의 유닉스). 특정 프로세스에 보내는 시그널은 커널에서 관리하는데 이때 커널은 프로세스에게 보낼 시그널을 한개 이상 유지할수 없다. 시그널을 받게 되면, 프로세스는 시그널 핸들러(신호 처리기)를 이용해서 시그널에 대한 처리를 하게 된다. 이때 즉 시그널 에 대한 처리가 끝나지 않은 상태에서 시그널이 발생되면 어떻게 될까 ? 시그널 처리중 동일한 시그널이 들어온다면 이 시그널은 블럭(보류)되었다가 핸들러가 처리를 끝나면 바로 전달된다. 이유는 시그널 이 발생되어서 해당 시그널에 대한 핸들러가 실행되면, 핸들러 실행이 종료되기까지 발생된 시그널에 대해서 block 을 하기 때문이다. 그런데 동일한 시그널이 2개가 발생을 한다면? 커널은 시그널의 대기열을 유지할수 없으므로 마지막에 도착한 시그널은 사라지게 된다. 만약 다른 종류의 시그널이 발생한다면, 그 즉시 시그널이 전달된다.기존 시그널 핸들러가 작업중이던 말던 그 시점에서 새로운 시그널을 받아들이고, 핸들러를 빠져나가게 된다. 그리고 다시 복귀하지 않는다. 그럼 시그널은 신뢰하기 힘들겠군요? 시그널이 큐잉 되지 않는다는 점은 짧은 시간에 여러개의 시그널이 발생할때 시그널을 잃어버릴수도 있다라는 것을 의미한다. 물론 하나의 프로세스에 대해서 매우 짧은 시간에 시그널이 다수 발생하는 일은 그리 흔하지 않긴 하겠지만 가끔은 문제가 될소지가 있다. 우리가 일반 시그널이 큐잉 되도록 커널을 뜯어 고칠수는 없는 문제이므로, 이걸 완벽하게 해결할수는 없다. 그러나 핸들러를 최소한 아토믹 한 코드로 만듬으로써 이러한 문제의 발생을 줄일수는 있을것이다. 그렇지 않고 커널차원에서 이러한 문제를 해결하고자 한다면 리얼타임 시그널을 사용해야 할것이다. 가장 큰 문제는 시그널핸들러 처리중에 다른 종류의 시그널이 발생했을때이다. 위에서 말했듯이 이럴경우 핸들러 처리도중에 빠져나가게 되고, 다시 핸들러로 복귀하지 않게 된다. 이건 꽤 심각할수 있는데, 시그널을 받아서 어떠한 파일 작업을 하고 있는데, 도중에 다른 시그널이 들어와 버리면, 제대로된 파일작업결과를 보증할수 없을것이다. 다행히 Unix 에서는 위의 문제들을 해결할수 있는 시그널 제어 관련 함수들을 제공한다. 이문서의 뒷부분에서 이에 대한 내용을 다루게 될것이다. 다음은 시그널의 이러한 특징을 테스트하기 위한 예제 코드이다. 예제: sigint.c#include <signal.h> #include <stdio.h> #include <string.h>
void sig_int(); void sig_usr();
int main() { char buf[255]; int i= 0;
if ((signal(SIGINT, sig_int)) == SIG_ERR) { perror("signal setting error : "); exit(1); } if ((signal(SIGUSR2, sig_usr)) == SIG_ERR) { perror("signal setting error : "); exit(1); }
while(1) { printf("%d\n", i); sleep(1); i++; }
}
void sig_int() { fprintf(stderr, "SIGINT !!!!\n"); sleep(5); }
void sig_usr() { fprintf(stderr, "SIGUSR !!!!\n"); }
|
위 프로그램을 컴파일해서 실행을 시켜보자 [yundream@localhost test]# ./sigtest 1 2 3
|
이제 CTRL+C 를 입력해서 SIGINT 를 발생시켜보자. 그러면 프로세스는 SIGINT 신호를 받게 되고 시그널핸들러인 sig_int 를 호출할것이다. sig_int 는 "SIGINT !!!!\n" 을 호출하고 5초동안 잠들게 되는데, 이때 계속 해서 CTRL+C 를 한 10번 정도 입력해보자. 그럼 5초후에 프로세스에 다시 SIGINT 가 발생함을 알수 있을것이다. 여기서 다시 5초를 기다리면 시그널이 다시 전달될까 ? 물론 전달되지 않는다. 단지 같은 시그널에 대해서 한번에 하나의 시그널만 block(대기) 할수 있기 때문에, 나머지 9개의 시그널은 전무 무시되어 버린다. 그럼 이제 sig_int 핸들러를 호출하고 있는도중에 SIGUSR2 시그널을 발생시키면 어떻게 될까 ? 이 테스트는 ./sigtest 를 실행시키고 CTRL+C 를 입력 SIGINT 를 발생시키고, 핸들러를 호출하는 중에 쉘에서 kill 명령을 써서 sigtest 의 pid 로 SIGUSR2 시그널을 보내면 될것이다. [yundream@localhost test]# ps -aux | grep sigtest yundream 2176 0.0 0.1 1348 344 pts/5 S 23:48 0:00 ./sigtest [yundream@localhost test]# kill -SIGUSR2 2176
|
물론 kill 을 통해 시그널을 발생시키기 전에 ./sigtest 에서 SIGINT를 발생시켜야 한다. 위와 같이 해서 SIGUSR2 시그널을 발생시키면 어떻게 될까 ? sig_int 핸들러가 작업을 끝낼때 까지 기다리고 나서 SIGUSR2 가 전달될까 ? 답은 그 즉시 전달된다 이다. sig_int 핸들러가 수행중이건 아니건 곧바로 SIGUSR2 가 전달되고 sig_usr 핸들러가 실행됨을 볼수 있을것이다. 이러한 문제들의 대한 해법은 이문서의 뒷부분에서 다루도록 하겠다. signal 관렴함수지금까지 시그널의 개론적인 면을 살펴봤으니 실제 시그널을 보내고/받고/제어하기 위한 어떤 함수들이 있는지 살펴보도록 하겠다. 신호 보내기 함수Unix 에서는 다음과 같은 신호를 보내기 위한 함수를 제공한다. #include #include
int kill(pid_t pid, int sig); int raise(int sig);
|
kill 은 프로세스 그룹 혹은 프로세스에 시그널을 보낼때 사용된다. pid 가 0보다 큰 양수이면 해당 pid 를 가지는 프로세스에게 sig 시그널을 보내며, pid 가 0이면 현재 프로세스가 속한 프로세스 그룹의 모든 프로세스에게 시그널을 보낸다. pid 가 -1이면 1번 프로세스를 제외한 모든 프로세스에게, -1 보다 작으면 자신이 가지는 프로세스 그룹의 모든 프로세스에게 시그널을 보낸다. raise 는 자기자신에게 sig 시그널을 보내는데, kill(getpid(), sig)로 동일한 일을 할수 있다. 신호 제어 함수지난번 기사인 signal다루기(1)에서 에제 sig_hup.c 를 컴파일 해서 테스트 해보았다면 새로 execl 된 프로세스에서는 시그널 작동이 제대로 되지 않는다는 것을 알수 있을것이다. 이유는 오늘 내용을 조금 생각해 보면서 읽었다면 충분히 알아낼수 있을것이다. sig_hup 에서 SIGHUP시그널을 전달받아 sig_handler 를 실행시키면, 핸들러가 끝나기 전가지 SIGHUP 를 블럭시키게 된다. 핸들러에서 execl 을 호출하므로 이 핸들러는 절대 종료될수가 없게 된다. 당연히 SIGHUP 시그널은 계속 블럭 된채로 남게 되고, 새로 들어오는 SIGHUP 는 모두 무시되게 된다. 이 문제를 해결하기 위해서는 코드가 시작될때 해당 시그널이 블럭되어 있는지 확인해서 블럭을 해제시켜주면 될것이다. 또한 시그널을 그룹지워서 관리하면 여러개의 시그널을 동시에 관리할수 있음으로 편리할것이다. 이러한 시그널 제어와 그룹핑을 위해서 Unix 는 다음과 같은 함수들을 제공한다. // 시그널 그룹관리를 위한 함수 int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signum); int sigdelset(sigset_t *set, int signum); int sigismember(const sigset-t *set, int signum);
// 시그널(그룹) 제어를 위한 함수 int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); int sigpending(sigset_t *set); int sigsuspend(const sigset_t *mask);
| sigemptyset 은 set 이 가르키는 시그널 집합을 초기화 한다. sigfillset 은 set 이 모든 신호를 포함하도록 초기화 한다. sigaddset 은 set에 시그널 signum 을 추가한다. sigdelset 은 set에서 시그널 signum 을 삭제한다. sigismember 은 set에 시그널 signum 이 포함되어 있는지 검사한다. sigprocmask 은 시그널 마스크를 검사하고 변경하기 위해서 사용된다. 간단히 말해서 해당 시그널에 대해서 BLOCK, UNBLOCK 를 하기 위해서 사용한다. sigpending 은 전달된 시그널(대기하고 있는시그널)에 대한 검사를 하기 위해서 사용된다. sigsuspend 해당 신호가 발생할때까지 프로세스를 중단시킨다. 이상 시그널 그룹관리와 이의 제어를 위한 함수를 알아봤는데, 이 사이트의 목적인 "예제를 통한 이해" 를 위해서 간단한 예제를 준비했다. 이 예제는 signal다루기(1)의 sig_hup 에서 발견되었던 "시그널블럭" 문제를 위의 함수들을 이용해서 해결하도록 할것이다. 예제: sig_hup2.c #include <signal.h> #include <unistd.h>
void sig_handler(int signo);
int main() { int i = 0; sigset_t newmask, oldmask;
printf("Program start\n");
if (signal(SIGHUP, (void *)sig_handler) == SIG_ERR) { perror("signal set error "); exit(0) ; }
sigemptyset(&newmask); sigaddset(&newmask, SIGHUP); if (sigprocmask(SIG_UNBLOCK, &newmask, &oldmask) < 0) { perror("sigmask error : "); exit(0); }
while(1) { printf("%d\n", i); i++; sleep(1); } return 1; }
void sig_handler(int signo) { execl("./sig_hup2", 0); }
| 코드는 간단하다. 먼저 sigemptyset를 이용해서 newmaskset 을 비우고, sigaddset 를 이용해서 여기에 SIGHUP를 추가 시켰다. 그리고 sigprocmask 를 이용해서 newmaskset 에 포함된 시그널들에 대해서 블럭을 해제하도록 했다. 그러므로 핸들러가 종료되지 않아서 시그널이 블럭된 상태라도, 블럭해제가 되고 코드는 문제없이 작동하게 될것이다. 신호 받기 함수지금까지 우리는 신호를 받기 위해서 signal 이라는 함수를 사용했었다. #include void (*signal(int signum, void (*handler)(int)))(int);
|
signal 의 원형은 위와 같다. 사용방법은 몇개의 예제에서 이미 보아왔음으로 따로 설명하지 않겠다. 그러나 현재는 위의 signal 은쓰지 않고 대신 sigaction 함수를 사용한다. signal 은 ANSI C 에 의해서 정의된 함수인데, 신호에 대한 정의가 애매한 불안정한 함수이다. 그러므로 예전쏘쓰와의 호환을 위한 목적이 아니면 사용하지 않도록 한다. sigaction 은 POSIX.1 에 의해서 제안된 안정된 신호체제를 제공한다. #include int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
|
signum 은 명시될 시그널 번호이다. struct sigaction 은 다음과 같이 정의 된다. struct sigaction { void (*sa_handler)(int); // signum 과 관련된 핸들러 함수 void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; // 시그널 처리동안 블럭되어야할 시그널의 마스크 int sa_flags; // 시그널의 처리 행위 조절을 위한 플래그 void (*sa_restorer)(void); // 사용되지 않는다. }
|
위의 구조체에서처럼 단지 시그널번호와 핸들러만을 넘겨주는 signal 과 달리 구조체 멤버를 통해서 다양한 정보를 넘겨주게 되며, 이러한 특성을 이용해서 시그널마스킹, 관리, 핸들러를 유기적으로 묶어줄수 있게 된다. 마지막으로 "예제: sigint.c" 를 sigaction 버젼으로 작성하고 sigint.c 의 문제점이였던, 시그널 핸들러 실행중 다른 시그널이 들어왔을경우 중단되어 버리는 문제를 해결하도록 코드를 재 작성하였다. 예제: sigint2.c#include <signal.h> #include <unistd.h> #include <string.h> #include <stdio.h>
void sig_int(int signo); void sig_usr(int signo);
int main() { int i = 0; struct sigaction intsig, usrsig;
usrsig.sa_handler = sig_usr; sigemptyset(&usrsig.sa_mask); usrsig.sa_flags = 0;
intsig.sa_handler = sig_int; sigemptyset(&intsig.sa_mask); intsig.sa_flags = 0;
if (sigaction(SIGINT, &intsig, 0) == -1) { printf ("signal(SIGALRM) error"); return -1; }
if (sigaction(SIGUSR2, &usrsig, 0) == -1) { printf ("signal(SIGUSR2) error"); return -1; }
while(1) { printf("%d\n", i); i++; sleep(1); } }
void sig_int(int signo) { sigset_t sigset, oldset; sigfillset(&sigset); // 새로들어오는 모든 시그널에 대해서 block 한다. if (sigprocmask(SIG_BLOCK, &sigset, &oldset) < 0) { printf("sigprocmask %d error \n", signo); } fprintf(stderr, "SIGINT !!!!\n"); sleep(5); }
void sig_usr(int signo) { printf("sig_usr2\n");
}
|
sig_int 핸들러를 호출하게 되면 sigfillset 를 이용해서 모든 시그널을 sigset 에 입력하고, 여기에 대해서 블럭을 하게 된다. 그러므로 새로 도착한 시그널은 현재 핸들러가 끝나서 블럭을 해제하기 전까지대기하게 된다. 퍼 올 생각은 없었는데..인터넷에 있는 데이터의 장기 보존성을 보장하기 힘들어 이런 선택을 하는것이니 특히 국내 조인시 위키등에는 양해를 부탁드립니다.
# by ydhoney | 2008/02/25 16:28 | IT&Linux | 트랙백 | 덧글(1)
<< 이전 페이지 | 다음 페이지 >>
|
|