|
楼主 |
发表于 2007-8-15 14:15:05
|
显示全部楼层
向子进程发信号
如下代码:
- /*
- forksignal2.c
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <signal.h>
- int isWorking = 1;
- void parent_fork(pid_t pid)
- {
- while(isWorking)
- {
- printf("0. 退出\n");
- printf("1. 向子进程发信号\n");
- printf("2. 退出子进程\n");
- printf("请输入您的选择: \n");
- scanf("%d", &isWorking);
- switch(isWorking)
- {
- case 0:
- break;
- case 1:
- kill(pid, 16);
- case 2:
- if (pid == 0)
- {
- printf("子进程不存在\n");
- break;
- }
- kill(pid, 17);
- pid = 0;
- break;
- default:
- isWorking = 0;
- }
- }
- }
- void sub_fork_working()
- {
- printf("别烦我,正忙着呢!\n");
- }
- void sub_fork_quit()
- {
- isWorking = 0;
- }
- void sub_fork()
- {
- signal(16, sub_fork_working);
- signal(17, sub_fork_quit);
- while(isWorking)
- {
- sleep(1);
- }
- }
- int main()
- {
- pid_t pid;
- pid = fork();
- if (pid > 0)
- parent_fork(pid);
- else
- sub_fork();
- return 0;
- }
复制代码
设计本意,父进程向子进程发送信号16则子进程回显一信息后继续运行,父进程向子进程发送信号17则子进程退出。运行结果如下:
- root@yxm:~/c++/test# cc forksignal2.c -o forksignal2
- root@yxm:~/c++/test# ./forksignal2
- 0. 退出
- 1. 向子进程发信号
- 2. 退出子进程
- 请输入您的选择:
- 1
- 别烦我,正忙着呢!
- 0. 退出
- 1. 向子进程发信号
- 2. 退出子进程
- 请输入您的选择:
- 1
- 栈失效
- root@yxm:~/c++/test# ./forksignal2
- 0. 退出
- 1. 向子进程发信号
- 2. 退出子进程
- 请输入您的选择:
- 2
- 0. 退出
- 1. 向子进程发信号
- 2. 退出子进程
- 请输入您的选择:
- 2
- 子进程不存在
- 0. 退出
- 1. 向子进程发信号
- 2. 退出子进程
- 请输入您的选择:
- 0
- root@yxm:~/c++/test#
复制代码
回头检查源文件,发现有逻辑错误,修改后代码如下:
- /*
- forksignal2.c
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <signal.h>
- int isWorking = 1;
- void parent_fork(pid_t pid)
- {
- while(isWorking)
- {
- printf("0. 退出\n");
- printf("1. 向子进程发信号\n");
- printf("2. 退出子进程\n");
- printf("请输入您的选择: ");
- scanf("%d", &isWorking);
- switch(isWorking)
- {
- case 0:
- break;
- case 1:
- if (pid == 0)
- {
- printf("子进程不存在\n");
- break;
- }
- kill(pid, 16);
- break;
- case 2:
- if (pid == 0)
- {
- printf("子进程不存在\n");
- break;
- }
- kill(pid, 17);
- pid = 0;
- break;
- default:
- isWorking = 0;
- }
- }
- }
- void sub_fork_working()
- {
- printf("别烦我,正忙着呢!\n");
- }
- void sub_fork_quit()
- {
- printf("子进程退出\n");
- isWorking = 0;
- }
- void sub_fork()
- {
- signal(16, sub_fork_working);
- signal(17, sub_fork_quit);
- while(isWorking)
- {
- sleep(1);
- }
- }
- int main()
- {
- pid_t pid;
- pid = fork();
- if (pid > 0)
- parent_fork(pid);
- else
- sub_fork();
- return 0;
- }
复制代码
执行结果:
- root@yxm:~/c++/test# cc forksignal2.c -o forksignal2
- root@yxm:~/c++/test# ./forksignal2
- 0. 退出
- 1. 向子进程发信号
- 2. 退出子进程
- 请输入您的选择: 1
- 0. 退出
- 1. 向子进程发信号
- 2. 退出子进程
- 请输入您的选择: 别烦我,正忙着呢!
- 1
- 0. 退出
- 1. 向子进程发信号
- 2. 退出子进程
- 请输入您的选择: 别烦我,正忙着呢!
- 1
- 别烦我,正忙着呢!
- 0. 退出
- 1. 向子进程发信号
- 2. 退出子进程
- 请输入您的选择: 2
- 子进程退出
- 0. 退出
- 1. 向子进程发信号
- 2. 退出子进程
- 请输入您的选择: 2
- 子进程不存在
- 0. 退出
- 1. 向子进程发信号
- 2. 退出子进程
- 请输入您的选择: 0
- root@yxm:~/c++/test#
复制代码
终于达到设计本意。
附:signal与kill的manpage
- root@yxm:~# man signal
- Reformatting signal(2), please wait...
- SIGNAL(2) Linux Programmer's Manual SIGNAL(2)
- NAME
- signal - ANSI C signal handling
- SYNOPSIS
- #include <signal.h>
- typedef void (*sighandler_t)(int);
- sighandler_t signal(int signum, sighandler_t handler);
- DESCRIPTION
- The signal() system call installs a new signal handler for the sig-
- nal with number signum. The signal handler is set to sighandler
- which may be a user specified function, or either SIG_IGN or
- SIG_DFL.
- Upon arrival of a signal with number signum the following happens.
- If the corresponding handler is set to SIG_IGN, then the signal is
- ignored. If the handler is set to SIG_DFL, then the default action
- associated with the signal (see signal(7)) occurs. Finally, if the
- handler is set to a function sighandler then first either the han-
- dler is reset to SIG_DFL or an implementation-dependent blocking of
- the signal is performed and next sighandler is called with argument
- signum.
- Using a signal handler function for a signal is called "catching the
- signal". The signals SIGKILL and SIGSTOP cannot be caught or
- ignored.
- RETURN VALUE
- The signal() function returns the previous value of the signal han-
- dler, or SIG_ERR on error.
- PORTABILITY
- The original Unix signal() would reset the handler to SIG_DFL, and
- System V (and the Linux kernel and libc4,5) does the same. On the
- other hand, BSD does not reset the handler, but blocks new instances
- of this signal from occurring during a call of the handler. The
- glibc2 library follows the BSD behaviour.
- If one on a libc5 system includes <bsd/signal.h> instead of <sig-
- nal.h> then signal() is redefined as __bsd_signal and signal has the
- BSD semantics. This is not recommended.
- If one on a glibc2 system defines a feature test macro such as
- _XOPEN_SOURCE or uses a separate sysv_signal function, one obtains
- classical behaviour. This is not recommended.
- Trying to change the semantics of this call using defines and
- includes is not a good idea. It is better to avoid signal() alto-
- gether, and use sigaction(2) instead.
- NOTES
- The effects of this call in a multi-threaded process are unspeci-
- fied.
- The routine handler must be very careful, since processing elsewhere
- was interrupted at some arbitrary point. POSIX has the concept of
- "safe function". If a signal interrupts an unsafe function, and
- handler calls an unsafe function, then the behavior is undefined.
- Safe functions are listed explicitly in the various standards. The
- POSIX 1003.1-2003 list is
- _Exit() _exit() abort() accept() access() aio_error() aio_return()
- aio_suspend() alarm() bind() cfgetispeed() cfgetospeed()
- cfsetispeed() cfsetospeed() chdir() chmod() chown() clock_gettime()
- close() connect() creat() dup() dup2() execle() execve() fchmod()
- fchown() fcntl() fdatasync() fork() fpathconf() fstat() fsync()
- ftruncate() getegid() geteuid() getgid() getgroups() getpeername()
- getpgrp() getpid() getppid() getsockname() getsockopt() getuid()
- kill() link() listen() lseek() lstat() mkdir() mkfifo() open() path-
- conf() pause() pipe() poll() posix_trace_event() pselect() raise()
- read() readlink() recv() recvfrom() recvmsg() rename() rmdir()
- select() sem_post() send() sendmsg() sendto() setgid() setpgid()
- setsid() setsockopt() setuid() shutdown() sigaction() sigaddset()
- sigdelset() sigemptyset() sigfillset() sigismember() signal() sig-
- pause() sigpending() sigprocmask() sigqueue() sigset() sigsuspend()
- sleep() socket() socketpair() stat() symlink() sysconf() tcdrain()
- tcflow() tcflush() tcgetattr() tcgetpgrp() tcsendbreak() tcsetattr()
- tcsetpgrp() time() timer_getoverrun() timer_gettime() timer_set-
- time() times() umask() uname() unlink() utime() wait() waitpid()
- write().
- According to POSIX, the behaviour of a process is undefined after it
- ignores a SIGFPE, SIGILL, or SIGSEGV signal that was not generated
- by the kill(2) or the raise(3) functions. Integer division by zero
- has undefined result. On some architectures it will generate a
- SIGFPE signal. (Also dividing the most negative integer by -1 may
- generate SIGFPE.) Ignoring this signal might lead to an endless
- loop.
- See sigaction(2) for details on what happens when SIGCHLD is set to
- SIG_IGN.
- The use of sighandler_t is a GNU extension. Various versions of
- libc predefine this type; libc4 and libc5 define SignalHandler,
- glibc defines sig_t and, when _GNU_SOURCE is defined, also sighan-
- dler_t.
- CONFORMING TO
- ANSI C
- SEE ALSO
- kill(1), alarm(2), kill(2), pause(2), sigaction(2), sigpending(2),
- sigprocmask(2), sigqueue(2), sigsuspend(2), killpg(3), raise(3),
- sigsetops(3), sigvec(3), feature_test_macros(7), signal(7)
- Linux 2.2 2000-04-28 SIGNAL(2)
- Manual page signal(2) line 75/114 (END)
复制代码
- root@yxm:~# man 2 kill
- Reformatting kill(2), please wait...
- KILL(2) Linux Programmer's Manual KILL(2)
- NAME
- kill - send signal to a process
- SYNOPSIS
- #include <sys/types.h>
- #include <signal.h>
- int kill(pid_t pid, int sig);
- DESCRIPTION
- The kill() system call can be used to send any signal to any process
- group or process.
- If pid is positive, then signal sig is sent to pid.
- If pid equals 0, then sig is sent to every process in the process
- group of the current process.
- If pid equals -1, then sig is sent to every process for which the
- calling process has permission to send signals, except for process 1
- (init), but see below.
- If pid is less than -1, then sig is sent to every process in the
- process group -pid.
- If sig is 0, then no signal is sent, but error checking is still
- performed.
- For a process to have permission to send a signal it must either be
- privileged (under Linux: have the CAP_KILL capability), or the real
- or effective user ID of the sending process must equal the real or
- saved set-user-ID of the target process. In the case of SIGCONT it
- suffices when the sending and receiving processes belong to the same
- session.
- RETURN VALUE
- On success (at least one signal was sent), zero is returned. On
- error, -1 is returned, and errno is set appropriately.
- ERRORS
- EINVAL An invalid signal was specified.
- EPERM The process does not have permission to send the signal to
- any of the target processes.
- ESRCH The pid or process group does not exist. Note that an exist-
- ing process might be a zombie, a process which already com-
- mitted termination, but has not yet been wait()ed for.
- NOTES
- The only signals that can be sent task number one, the init process,
- are those for which init has explicitly installed signal handlers.
- This is done to assure the system is not brought down accidentally.
- POSIX 1003.1-2001 requires that kill(-1,sig) send sig to all pro-
- cesses that the current process may send signals to, except possibly
- for some implementation-defined system processes. Linux allows a
- process to signal itself, but on Linux the call kill(-1,sig) does
- not signal the current process.
- POSIX 1003.1-2003 requires that if a process sends a signal to
- itself, and the sending thread does not have the signal blocked, and
- no other thread has it unblocked or is waiting for it in sigwait(),
- at least one unblocked signal must be delivered to the sending
- thread before the kill().
- BUGS
- In 2.6 kernels up to and including 2.6.7, there was a bug that meant
- that when sending signals to a process group, kill() failed with the
- error EPERM if the caller did have permission to send the signal to
- any (rather than all) of the embers of the process group. Notwith-
- standing this error return, the signal was still delivered to all of
- the processes for which the caller had permission to signal.
- LINUX HISTORY
- Across different kernel versions, Linux has enforced different rules
- for the permissions required for an unprivileged process to send a
- signal to another process. In kernels 1.0 to 1.2.2, a signal could
- be sent if the effective user ID of the sender matched that of the
- receiver, or the real user ID of the sender matched that of the
- receiver. From kernel 1.2.3 until 1.3.77, a signal could be sent if
- the effective user ID of the sender matched either the real or
- effective user ID of the receiver. The current rules, which conform
- to POSIX 1003.1-2001, were adopted in kernel 1.3.78.
- CONFORMING TO
- SVr4, SVID, POSIX.1, X/OPEN, 4.3BSD, POSIX 1003.1-2001
- SEE ALSO
- _exit(2), killpg(2), signal(2), sigqueue(2), tkill(2), exit(3),
- capabilities(7), signal(7)
- Linux 2.6.7 2004-06-24 KILL(2)
- Manual page kill(2) line 60/99 (END)
复制代码 |
|