尝试linux下c编程之进程与信号

来源:互联网 发布:免费qq机器人软件 编辑:程序博客网 时间:2024/06/06 07:46
上过操作系统这门课,所以略知进程与信号的概念,当时进程学的还好些,毕竟xp下的进程,我们经常触及;可对于信号,我真晕了,什么wait(),signal()的...直到今天真正在linux下写写代码,才使我找到信号的真谛~尽管尝试的应用很简单,不过真的有所得!

1  信号

先回忆下信号的概念:信号是为了使进程获得某项重要通知而发送给它的重要事件。这时进程必须立即停止当前的工作,转而处理该信号。每一个信号都用一个整数代表信号的类型。
ps:这些信号定义在/usr/include/asm-i386/signal.h中,不过现在有的定义好的信号也不知道用处,希望知道的人能给些提示.

键盘可以发送下列信号:
Ctrl-C:  发送 SIGINT, 缺省情况下,进程立即终止
Ctrl-Z:  发送SIGTSTP,缺省情况下,进程被挂起
Ctrl-/:  发送SIGABRT,缺省情况下,进程立即中止,类似于Ctrl-C,但是有更强灵活性

当在终端输入fg命令时可以重新激活挂起的进程,它发送SIGCONT信号

上述我们可得键盘可以发送信号,若想改变其缺省状态,我们可以编写函数void catch_int(int sig_num),然后在main函数中调用signal(SIGINT, catch_int)

代码如下:
#include <stdio.h>
#include 
<unistd.h>
#include 
<signal.h>

void catch_int( int sig_num )
{
  
//reset SIGINT, catch_int
  signal( SIGINT, catch_int );
  printf( 
"Control-C is ignored, please don't waste time.%d ", sig_num);
  fflush( stdout );       
//在多进程时常常用到fflush();
}

int main( int argc, char* argv[ ] )
{
  printf( 
"Want to try control-C? " );
  signal( SIGINT, catch_int );
  
//catch_int(SIGINT);

  
//into while
  while1 )
    pause(  );
  
return 0;
}

2 应用信号做timeout

SIGALRM是定时的信号
#include <stdio.h>
#include 
<unistd.h>
#include 
<signal.h>
#include 
<stdlib.h>

void catch_alarm( int sig_num )

  printf( 
" Sorry, time limit reached. " );
  alarm( 
0 );
  exit( 
0 ); 
}

  

int main( int argc, char *argv[  ] )
{
  printf( 
"Your username( 5 second limit ): " );
  fflush( stdout );
  
  signal( SIGALRM, catch_alarm );        
//设置当有SIGALRM信号时操作,模认为输出ALARM xxx后退出程序
  alarm( 5 );
  
  
char *a;
  fgets( a, 
40, stdin );       //从stdin中取用户输入的用户名
  
  printf( 
"Your username is: %s ", a );
  
return 0;
}


3 进程与信号

进程概念:  执行一个代码段,有自己的堆栈和内存页面的实体

fork()命令建立信进程,与普通函数不同的是他的返回有两次。fork()把当前的进程分为两个进程,一个父进程和一个子进程。原来进程的所有内存页面在fork时分为相同的两份,所以子进程与父进程都是用相同的映射。在父进程中,它的返回值是子进程的进程号;在子进程中,它的返回值是0;错误返回-1。

因此如果我们写如下函数:
if(fork() = =0)
{
printf(“This is the child process/n”);
}else{
printf(“This is the parent process/n”);
}
输出结果显示为
This is the child process
This is the parent process
呵呵,很令人奇怪吧....if & else 均中标...

说完fork(),接下来恼人的是wait()函数。
wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。当子进程退出时,实际上它的状态处于zombie,只有当父进程调用wait()确认后,子进程才会真正意义上kill。反过来当父进程先退出时,子进程会继续进行。

实例代码如下:
#include <sys/types.h>
#include 
<sys/wait.h>
#include 
<stdio.h>
#include 
<stdlib.h>

int main( int argc, char *argv[  ] )
{
  pid_t child_pid;
  
int child_status;

  child_pid 
= fork(  );
  
  
switch( child_pid ){
  
case -1:
    perror( 
"fork" );
    exit( 
1 );
  
case 0:        //中标
    printf( "child: hello from child process " );
    sleep( 
5 );
    exit( 
0 );
  
default:       //中标
    printf( "parent: I am waiting child process " );
    wait( 
&child_status );                   //父进程会无所事事
  }

  
return 0;
}


我们为了解决wait()给父进程带来的无所事事,我们用信号量来解决
当子进程结束时,会发送SIGCHLD信号到父进程,所以我们获取此信号再加些操作就可以起到解决问题的目的啦~~

#include <stdio.h>
#include 
<unistd.h>
#include 
<sys/types.h>
#include 
<sys/wait.h>
#include 
<signal.h>
#include 
<stdlib.h>


void signal_handler( int n )
{
  
int child_status;
  wait( 
&child_status );
  printf( 
"child exited. " );
}



int main( int argc, char *argv[  ] )
{
  pid_t child_pid;
  
int child_status;
  
  signal( SIGCHLD, signal_handler );  
//when child process exit( the status of zombie )    获取SIGCHLD信号
  
  child_pid 
= fork(  );
  
int i=0;
  
switch( child_pid ){
  
case -1:
    perror( 
"fork" );
    exit( 
1 );
  
case 0:
    printf( 
"child: hello from child process " );
    sleep( 
3 );                              //我就不退出,看父进程傻等我不  ^_^
    exit( 0 );
  
default:
    
for( i;i<10;i++ ){                    
      printf( 
"%d", i );                             //会连续输出
      fflush( stdout );                   //不写的话会有bug
      sleep( 1 );
    }

  }

  
return 0;
}



OK,今天进行到此~~
不过父进程子进程还是不能交互,等明天或者过两天,管道研究
至于进程与进程的交互,就要用到消息了吧...
继续学习...
原创粉丝点击