// sched_setscheduler 使用の無限ループプロセスをブロックする // // 原理: // 一般スケジューリングポリシーの子プロセスが一定時間おきに親に信号を送る。 // 最優先プロセスの親が 子からの信号が跡絶えたときに, 全プロセスを // チェックし, 強制的にポリシー変更をする #include #include #include #include #include #include #include #include #include #include // 一般プロセスの停止確認期間(秒) #define FREEZE_PERIOD 5 // 確認用の通信間隔 #define PING_PERIOD 2 static int term=0; void sigchld(int t) { fprintf(stderr,"Monitoring child process died for some reason\n"); term=1; } void sigterm(int t) { term=1; }; void ClearAllSchedulingPolicy(void) { int i,p; pid_t me=getpid(); struct sched_param sp; sp.sched_priority=0; for(i=1;i<65536;i++) { if(i==me) continue; p=sched_getscheduler(i); if((p>=0)&&(p!=SCHED_OTHER)) { fprintf(stderr, "PID %d is not SCHED_OTHER. Change scheduling policy\n",i); sched_setscheduler(i,SCHED_OTHER,&sp); } } } int main(void) { int pipefd[2]; pid_t pid; struct sched_param sp; int t; char buff[2]; fd_set readfds; struct timeval tv; // パイプ設置 if(pipe(pipefd)) { perror("freezeblock(pipe)"); return 1; } if(setpriority(PRIO_PROCESS,0,-1)) { perror("freezeblock(setpriority)"); fprintf(stderr,"Is this program run under root?\n"); return 1; } pid=fork(); if(pid<0) { perror("freezeblock(fork)"); return 1; } if(pid==0) { // child process close(pipefd[0]); while(1) { sleep(PING_PERIOD); write(pipefd[1],".",1); } } // parent process close(pipefd[1]); // こちらも最優先に遷移 sp.sched_priority=99; if(sched_setscheduler(0,SCHED_FIFO,&sp)) { perror("freezeblock(sched_setscheduler)"); kill(pid,SIGINT); while(waitpid(pid,&t,0)!=pid) ; return 1; } signal(SIGCHLD,sigchld); signal(SIGHUP,sigterm); signal(SIGINT,sigterm); signal(SIGQUIT,sigterm); signal(SIGTERM,sigterm); while(term==0) { tv.tv_usec=0; tv.tv_sec=FREEZE_PERIOD; FD_ZERO(&readfds); FD_SET(pipefd[0],&readfds); t=select(pipefd[0]+1,&readfds,NULL,NULL,&tv); if(t<0) break; if(t==0) { fprintf(stderr,"FREEZE detection\n"); ClearAllSchedulingPolicy(); } if(FD_ISSET(pipefd[0],&readfds)) { if(read(pipefd[0],buff,1)>0) { putchar(buff[0]); fflush(stdout); } else break; } } // 子プロセス停止 kill(pid,SIGINT); while(waitpid(pid,&t,0)!=pid) ; close(pipefd[0]); fprintf(stderr,"freezeblock: successfully terminated\n"); return 0; }