펄에서 C의 alarm과 같은 기능
글쓴이: urmajest / 작성시간: 화, 2005/03/08 - 12:42오전
안녕하세요.
특정 시간 단위로 정해진 명령을 수행하도록 하고 싶은데요.
while(1) { `do something`; sleep(1); }
위와 같이 하면 1초 단위가 아닌 1초+"do something"에 걸린 시간 단위가 되겠죠.
여기서 정확히 1초단위로 작업을 수행하고 싶거든요.
C에서는 setitimer(alarm)와 sigaction을 이용해서 가능했는데,
perl에서는 어떻게 해야하는지 모르겠네요.
(busy waiting이 아닌 방법을 알려주세요. ^^)
Forums:
요런거 원하시나요?
요런거 원하시나요?
http://search.cpan.org/~lbaxter/Sys-SigAction/lib/Sys/SigAction.pm
윗분 말씀하신 모듈은 OO-style로 만든 거고,alarm() 은
윗분 말씀하신 모듈은 OO-style로 만든 거고,
alarm() 은 perl에 원래 있습니다(perldoc -f alarm).
(perl에는 유닉스 함수 대부분이 내장입니다)
초단위 이하로 setitimer()를 쓰고싶다면 Time::HiRes를 사용하세요.
setitimer()를 부르기 위해서 내장함수 syscall()을 써서 할 수도 있다지만
별로 추천하고 싶지는 않군요.
http://search.cpan.org/dist/Time-HiRes/HiRes.pm
--
익스펙토 페트로눔
perl도 똑같습니다.구글에서 'perl signals'로 검색하
perl도 똑같습니다.
구글에서 'perl signals'로 검색하시면 자료 많습니다.
Signals
Perl uses a simple signal handling model: the %SIG hash contains names or references of user-installed signal handlers. These handlers will be called with an argument which is the name of the signal that triggered it. A signal may be generated intentionally from a particular keyboard sequence like control-C or control-Z, sent to you from another process, or triggered automatically by the kernel when special events transpire, like a child process exiting, your process running out of stack space, or hitting file size limit.
For example, to trap an interrupt signal, set up a handler like this. Do as little as you possibly can in your handler; notice how all we do is set a global variable and then raise an exception. That's because on most systems, libraries are not re-entrant; particularly, memory allocation and I/O routines are not. That means that doing nearly anything in your handler could in theory trigger a memory fault and subsequent core dump.
sub catch_zap {
my $signame = shift;
$shucks++;
die "Somebody sent me a SIG$signame";
}
$SIG{INT} = 'catch_zap'; # could fail in modules
$SIG{INT} = \&catch_zap; # best strategy
The names of the signals are the ones listed out by kill -l on your system, or you can retrieve them from the Config module. Set up an @signame list indexed by number to get the name and a %signo table indexed by name to get the number:
use Config;
defined $Config{sig_name} || die "No sigs?";
foreach $name (split(' ', $Config{sig_name})) {
$signo{$name} = $i;
$signame[$i] = $name;
$i++;
}
So to check whether signal 17 and SIGALRM were the same, do just this:
print "signal #17 = $signame[17]\n";
if ($signo{ALRM}) {
print "SIGALRM is $signo{ALRM}\n";
}
You may also choose to assign the strings 'IGNORE' or 'DEFAULT' as the handler, in which case Perl will try to discard the signal or do the default thing. Some signals can be neither trapped nor ignored, such as the KILL and STOP (but not the TSTP) signals. One strategy for temporarily ignoring signals is to use a local() statement, which will be automatically restored once your block is exited. (Remember that local() values are ``inherited'' by functions called from within that block.)
sub precious {
local $SIG{INT} = 'IGNORE';
&more_functions;
}
sub more_functions {
# interrupts still ignored, for now...
}
Sending a signal to a negative process ID means that you send the signal to the entire Unix process-group. This code sends a hang-up signal to all processes in the current process group (and sets $SIG{HUP} to IGNORE so it doesn't kill itself):
{
local $SIG{HUP} = 'IGNORE';
kill HUP => -$$;
# snazzy writing of: kill('HUP', -$$)
}
Another interesting signal to send is signal number zero. This doesn't actually affect another process, but instead checks whether it's alive or has changed its UID.
unless (kill 0 => $kid_pid) {
warn "something wicked happened to $kid_pid";
}
You might also want to employ anonymous functions for simple signal handlers:
$SIG{INT} = sub { die "\nOutta here!\n" };
But that will be problematic for the more complicated handlers that need to reinstall themselves. Because Perl's signal mechanism is currently based on the signal(3) function from the C library, you may sometimes be so misfortunate as to run on systems where that function is ``broken'', that is, it behaves in the old unreliable SysV way rather than the newer, more reasonable BSD and POSIX fashion. So you'll see defensive people writing signal handlers like this:
sub REAPER {
$waitedpid = wait;
# loathe sysV: it makes us not only reinstate
# the handler, but place it after the wait
$SIG{CHLD} = \&REAPER;
}
$SIG{CHLD} = \&REAPER;
# now do something that forks...
or even the more elaborate:
use POSIX ":sys_wait_h";
sub REAPER {
my $child;
while ($child = waitpid(-1,WNOHANG)) {
$Kid_Status{$child} = $?;
}
$SIG{CHLD} = \&REAPER; # still loathe sysV
}
$SIG{CHLD} = \&REAPER;
# do something that forks...
Signal handling is also used for timeouts in Unix, While safely protected within an eval{} block, you set a signal handler to trap alarm signals and then schedule to have one delivered to you in some number of seconds. Then try your blocking operation, clearing the alarm when it's done but not before you've exited your eval{} block. If it goes off, you'll use die() to jump out of the block, much as you might using longjmp() or throw() in other languages.
Here's an example:
eval {
local $SIG{ALRM} = sub { die "alarm clock restart" };
alarm 10;
flock(FH, 2); # blocking write lock
alarm 0;
};
if ($@ and $@ !~ /alarm clock restart/) { die }
For more complex signal handling, you might see the standard POSIX module. Lamentably, this is almost entirely undocumented, but the t/lib/posix.t file from the Perl source distribution has some examples in it.
그리고 누가 그랬는지 까먹었지만..어떤 개발자분은 C로 짜기전에 perl
그리고 누가 그랬는지 까먹었지만..어떤 개발자분은 C로 짜기전에 perl로 먼저 짜본다 하더군요..ㅎㅎ..그만큼 C에서 되는게 perl에서 안되는게 없고 perl에서 되는게 C에서 안되는게 없을만큼이라는 뜻인걸까요?
답변 감사드립니다 ^^펄 초보라 항상 연구실에서 누가 짜놓은 걸
답변 감사드립니다 ^^
펄 초보라 항상 연구실에서 누가 짜놓은 걸 보고 고치기만 하다보니,
그런 걸 몰랐군요 ^^
그런데 펄의 신택스는 꽤나 생소하네요.
열심히 공부해야겠네요 ^^
댓글 달기