【Linux-进程】进程控制及信号

问题:
    1.exit(状态码)返回状态码有什么意义?
    返回值被系统得到。系统根据状态码进行日志记录
    返回值被调用者得到:system/wait.程序会根据返回状态码进程对应处理。
    exit(状态码) = main函数中的return状态码;
    2.状态码的第二个字节才是exit()的返回值或者return值
    WEXITSTATUS(status),取出第二个字节

一、进程的基本控制
    1.进程的常见控制函数
         1.1 为什么需要控制进程?
         1.2 pause/sleep/usleep
         1.3 atexit on_exit
             #include <stdlib.h>
             int atexit(void (*function)(void));

             #include <stdlib.h>
             int on_exit(void (*function)(int , void *), void *arg);

             #include <stdio.h>
             #include <stdlib.h>
             void fun()
             {
                 printf("hello fun\n");
             }
             main()
             {
                 atexit(fun);
                 printf("hello main\n");
             }
             在进程退出之前,会回调function函数
         on_exit的function带参数的
    2.进程与文件锁
         2.1 在多进程下文件读写是共享的
         问题:
             怎么知道一个文件正在被另外进程读写?
         解决方案:
             文件锁(一般是建议锁)
         API:
             fcntl (文件锁受内核参数影响:强制锁,建议锁)
         编程技巧:
             对一个文件加锁
             判定一个文件是否存在锁(只要加一把锁,需要判定)
         函数说明:
             #include <unistd.h>
             #include <fcntl.h>
             int fcntl(int fd, int cmd, ... /* arg */ );
             返回值:
                 0:加锁成功
                 -1:加锁失败
             参数:
                 fd:被加锁的文件描述符号
                 cmd:锁的操作方式:F_SETLK(已经加锁,异常返回)  F_UNLK  F_SETLKW
                 struct flock *lk:锁的描述
                     l_type Type of blocking lock found.
                     l_whence
                            SEEK_SET.
                     l_start
                            Start of the blocking lock.
                     l_len  Length of the blocking lock.
                     l_pid  Process ID of the process that holds the blocking lock.

案例:
        1、过程:
            打开一个文件
            描述锁
            加锁
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

main()
{
  int fd = 0;
  struct flock lk = {0};
  int r = 0;
  fd = open("a.txt",O_RDWR);
  if(fd == -1) printf(":%m\n"),exit(-1);

  r = fcntl(fd,F_GETLK,&lk);
  if(r == 0) printf("get lock success!\n ");
  if(lk.l_type == F_WRLCK) printf("write lock\n ");
 
  printf("start:%d, len:%d\n ",lk.l_start,lk.l_len);
  printf("pid:%d\n ",lk.l_pid);
  while(1);
}

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

main()
{
  int fd;
  struct flock lk;
  int r;
  fd = open("a.txt",O_RDWR);
  if(fd == -1) printf(":%m\n"),exit(-1);
  lk.l_type = F_WRLCK;
  lk.l_whence = SEEK_SET;
  lk.l_start = 5;
  lk.l_len = 10;
  r = fcntl(fd,F_SETLK,&lk);
  if(r == 0) printf("Add lock success!\n ");
  else printf("Add lock failed!\n ");
  while(1);
}
锁也是一个进程可以共享的信息


二、信号
    1.信号的作用
    进程之间通信比较麻烦
    但进程之间又必须通信,比如父子进程之间
    作用:通知其他进程响应。进程之间通信机制。
    信号:接收信号的进程会马上停止,去执行信号的处理函数
        默认处理函数:打印信号信息,退出
        用户处理函数:自己的程序
    中断:软中断
案例:
    1.进程之中,默认信号处理
    2.进程之中,用户处理函数

    kill -s 信号 进程ID
    kill -信号 进程ID
    信号:数字1-31  34-64
         宏:SIGINT=2
    kill -l  查看所有的信号

    ctrl-C就是信号2 SIGINT
 
 

        信号SIGKILL SIGSTOP不能被处理
    

    2.信号发送与安装
    kill函数
    #include <sys/types.h>
        #include <signal.h>
        int kill(pid_t pid, int sig);
    正确:返回0;错误:返回-1
    进程ID:
        >0:发送信号到指定进程
        =0:发送信号到该进程所在进程组的所有进程
        =-1:发送给所有进程,除init进程外
        <0:发送给指定的进程组(组ID=进程值)
    3.信号的应用
    3.1延时器
        SIGALRM
        信号发出函数:alarm
    3.2定时器
        int settimer(
         int which;//计时方式 ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF
        const struct itimerval *val;//定时器参数
        struct itimer *oldval;//返回原来设置的时间,如果为NULL ,则不返回    
         )
    struct itimerval
         {
            struct timeval it_interval;//间隔时间
            struct timeval it_value//延时时间
        }
        struct timeval
        {
            long tv_sec;
            long tv_usec;   
        }

    #include <stdio.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/time.h>
    void deal()
    {
    printf("alarm\n");
    }
    main()
    {
        struct itimerval v = {0};
        signal(SIGALRM,deal);
        
        v.it_value.tv_sec = 5;
        v.it_interval.tv_sec = 1;
        setitimer(ITIMER_REAL,&v,0);
        //alarm(5);
        while(1);
    }
信号应用:
    系统与应用程序之间
    应用于应用程序之间
    父子进程之间
    
    案例:
demo1;
    使用定时器,实现多任务切换
    实现:
        实现七位随机数
        使用中断实现时间的显示
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#include <math.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
WINDOW *wtime,*wnumb;
int i = 0;

void showtime(int s)
{
  time_t tt;
  struct         tm *t;
  if(SIGALRM == s)
  {
        tt = time(0);
        t = localtime(&tt);
        mvwprintw(wtime,1,1,"%02d:%02d:%02d",t->tm_hour,t->tm_min,t->tm_sec);
        refresh();
        wrefresh(wtime);
        wrefresh(wnumb);
  }
}
main()
{
  int num = 0;
  struct itimerval timeVal = {0};
  initscr();
  curs_set(0);
  noecho();
  signal(SIGALRM,showtime);

  timeVal.it_value.tv_sec = 0;
  timeVal.it_value.tv_usec = 1;
  timeVal.it_interval.tv_sec = 1;  
  setitimer(ITIMER_REAL,&timeVal,0);
 
  wnumb = derwin(stdscr,3,11,(LINES-3)/2,(COLS-11)/2);
  wtime = derwin(stdscr,3,10,0,COLS-10);
  box(wnumb,0,0);
  box(wtime,0,0);
  while(1)
  {
        num = 0;
        for(i=0;i<7;i++)
        {
          num = num*10+rand()%10;
        }
        mvwprintw(wnumb,1,2,"%07d",num);
        refresh();
        wrefresh(wnumb);
        wrefresh(wtime);
        usleep(500000);
  }  
  endwin();
}



demo2:
    使用两个进程实现信号的传递
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <curses.h>
#include <math.h>

WINDOW *w;
int num = 0;
int isstop = 0;

void deal(int s)
{
  isstop = (s==SIGUSR1) ? 1 : 0;
}
main()
{
  int i = 0;
  initscr();
  curs_set(0);
  noecho();
  keypad(stdscr,TRUE);
  keypad(w,TRUE);
  w = derwin(stdscr,3,11,(LINES-3)/2,(COLS-11)/2);
  box(w,0,0);
  refresh();
  wrefresh(w);
 
  if(fork())
  {
        signal(SIGUSR1,deal);
        while(1)
        {
          if(isstop == 1)
          {
                pause();
                isstop = 0;
          }
          num = 0 ;
          for(i=0;i<7;i++)
          {
                num = num*10 + rand()%10;
          }
          mvwprintw(w,1,2,"%07d",num);
          refresh();
          wrefresh(w);
          usleep(100000);
        }
  }
  else
  {
        while(1)
        {
          getch();
          kill(getppid(),SIGUSR1);
        }
  }
  endwin();
}

    4.信号的可靠与不可靠以及信号的含义
    信号有丢失(信号压缩)
    由于历史的缘故:信号有压缩的需求
    可靠信号与不可靠信号

    早期信号1-31 31个信号,不可靠(与系统有关)
    后期信号34-64 可靠信号(用户信号)

    5.信号的操作
    信号导致的问题
    1.信号屏蔽
    int sigprocmask(int how,//操作方式  SIG_BLOCK SIG_UNBLOCK  SIG_SETMASK
        const sigset_t*sigs,//操作的信号集合
        sigset_t *oldsigs//返回原来操作的信号
        );
            1.1.声明一个信号集合
        sigset_t sigs;
        1.2.加入屏蔽信号
        一组信号集合维护函数:        
            1.2.1.清空集合sigemptyset
            1.2.2.添加信号到集合sigaddset
            1.2.3.从集合删除信号sigdelset
            1.2.4.添加所有信号到集合sigfillset
            1.2.5.判定某个集合是否在其中sigismember
sigmask.c
#include <stdio.h>
#include <signal.h>

main()
{
  int i = 0;
  sigset_t sigs;
  sigemptyset(&sigs);
  sigaddset(&sigs,SIGINT);
  sigprocmask(SIG_BLOCK,&sigs,0);
  for(i=0;i<10;i++)
  {
        printf("%d\n",i);
        sleep(1);
  }
  printf("i=%d\n",i);
  sigprocmask(SIG_UNBLOCK,&sigs,0);
  printf("over\n");
}
    这个程序可以屏蔽ctrl+C
        1.3.屏蔽信号
        1.4.接触屏蔽
    2.信号屏蔽的切换
        
        int sigsuspend(sigset_t *sigs);
        屏蔽新的信号,原来的信号失效
        sigsuspend是阻塞函数,对参数信号屏蔽
        对参数没有指定的信号不屏蔽,但当没有屏蔽的信号处理函数结束后返回
              sigsuspend返回条件:
        1、非屏蔽信号发生
        2、该信号触发且有处理函数,且处理函数返回
        作用:使原来屏蔽信号无效,开放原来的信号,使新的信号屏蔽,当某个信号处理函数处理完毕,sigsuspend恢复原来屏蔽信号,返回
    3.查询被屏蔽的信号
        sigpending(sigset_t *sig);
    6.信号与进程间数据传递
    sigqueue=kill
    sigaction=signal

1.进程控制 sleep pause

2.理解信号的中断流程

3.发射信号(shell/code)kill,处理信号

4.alarm与setitmer

5.信号应用:实现多任务/进程之间通信

6.信号使用+sleep/pause控制进程

7.信号屏蔽

8.了解sigpending与sigsuspend使用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值