linux 环境编程学习笔记 第16.17天 进程的基本控制,信号


 寒假学习 第16.17天 (linux 高级编程) 笔记 总结

 

一、进程的基本控制(进程的同步)

 

1.进程的常见控制函数

      pause   sleep/usleep

       atexit   on_exit

int atexit(void (*function)(void));    //注册终止函数(即main执行结束后调用的函数)

int on_exit(void (*function)(int , void *), void *arg); //跟atexit差不多,只不过函数可以带参数

 

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

void fun()
{
    printf("over!\n");
}

int main(int argc, const char *argv[])
{
    atexit(fun);    //注册,
    printf("Processs!\n");
    return 0;
}

 

 

2.进程与文件锁(锁有共享锁跟强制锁,内核编译不同)

     多进程下面文件的读写是共享的。

    怎么知道一个文件正在被另外进程读写?

        就是要使用文件锁。

         API:

              fcntl (文件锁受内核参数影响)

      对文件加锁     

      int fcntl(int fd, int cmd, ... /* arg */ ); 

                返回0加锁成功,-1加锁失败。

                 fd 加锁的文件符号

                 cmd 锁的操作方式 F_SETLK(如果已经加锁就异常返回)  F_UNLK  F_SETLCKW(已经加锁,者、则阻塞等待等到解锁)             

                 ... struct flock* 类型    

 

           struct flock {
               ...
               short l_type;    /* Type of lock: F_RDLCK,
                                   F_WRLCK, F_UNLCK */
               short l_whence;  /* How to interpret l_start:
                                   SEEK_SET, SEEK_CUR, SEEK_END */
               off_t l_start;   /* Starting offset for lock */
               off_t l_len;     /* Number of bytes to lock */
               pid_t l_pid;     /* PID of process blocking our lock
                                   (F_GETLK only) */
               ...
           };

 

 

例子:

setlock.c

 

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

int main(int argc, const char *argv[])
{
    int fd;
    struct flock lk;
    int r;
    fd=open("test.txt",O_RDWR);
    if(fd==-1) printf("error:%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("加锁成功!\n");
    else
        printf("加锁失败!\n");
    while(1);
        
    return 0;
}

 

getlock.c

 

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

int main(int argc, const char *argv[])
{
    int fd;
    struct flock lk={0};  //一定要初始化0
    int r;

    fd=open("test.txt",O_RDWR);
    if(fd==-1) printf("error:%m\n"),exit(-1);

    r=fcntl(fd,F_GETLK,&lk);

    if(lk.l_type=F_WRLCK){
        printf("写锁!\n");
    }

    printf("pid:%d,start:%d, len:%d\n",r,lk.l_pid,lk.l_start,lk.l_len);

    return 0;
}


锁也是一个进程可以共享的信息

 

 

 

二、信号

1.信号的作用

流程:

 

 信号发给操作系统,操作系统查找这个信号是否注册,如果注册系统就调用函数

                                                                                         没有注册则采用缺省处理(一般是调用打印信号提示,并终止程序)

 

       为了解决进程之间通信难。

     作用:通知其他进程响应。(其实就是进程之间一种通信机制)

     一般接受信号的进程会马上停止(软中断),并且调用信号的处理函数(默认的处理函数,或者用户的处理函数)。

例子:

 

2.信号的发送与安装

    kill   -s  信号  进程ID         //向指定的进程发送信号

    kill -l                                  //可以看所有的信号  ctrl+D 就相当于发送信号2(即SIGINT)

例子:

 

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void handle(int s)
{
    printf("信息发生\n");
}

int main(int argc, const char *argv[])
{
    signal(SIGINT,handle); //注册信号
    while(1)
    {
        printf("进程在执行!\n");
        sleep(1);
    }
    return 0;
}

当kill -s 2 pid 时(或直接ctrl+C)就会输出   “信号发送”

 

其中 SIGKILL与 SIGSTOP 信号是不能被处理的

int kill(pid_t pid, int sig);  //发送信号

pid:如果>0  发送到指定进程

          如果=0  发送信号到该进程所在进程组的所有进程

          如果=-1 发送给除init (1)之外的所有进程

          如果<0   发送给指定的进程组(组ID就是 它的绝对值)

例子:

 

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

int main(int argc, const char *argv[])
{
    while(1)
    {
        kill(4184,SIGINT);
        sleep(2);
    }
    return 0;
}

 

 

3.信号的应用(实现多任务)

    延时器 timeout

         信号:SIGALRM

         信号发送函数:unsigned int alarm(unsigned int seconds); //自向本进程发出

例子:

 

#include <stdio.h>
#include <signal.h>

void deal(int s)
{
    printf("起床!\n");
}

int main(int argc, const char *argv[])
{
    signal(SIGALRM,deal);
    alarm(5);
    while(1)
    {
        printf("AAAAA\n");
        sleep(1);
    }
    return 0;
}


定时器

 

       int getitimer(int which, struct itimerval *curr_value);
       int setitimer(int which, //计时方式  ITIMER_REAL真实时间  ITIMER_VIRTUAL程序暂用cpu的时间   ITIMER_PROF 进程跟系统的混合时间

                           const struct itimerval *new_value,  //定时器的时间参数

                           struct itimerval *old_value);   //返回原来设置的定时器,如果NULL 者不返回。

(set interval timter)

    struct itimerval {
               struct timeval it_interval;// 延时时间
               struct timeval it_value;   //间隔时间
           };

 struct timeval {
               time_t      tv_sec;            //秒
               suseconds_t tv_usec;   //毫秒

           };

例子:

 

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>

void deal(int s)
{
    printf("起床!\n");
}

int main(int argc, const char *argv[])
{
    struct itimerval val={0};
    signal(SIGALRM,deal);
    val.it_value.tv_sec=3;   //sec跟usec都为0的表无穷时间,不会触发
    val.it_interval.tv_sec=1;

    setitimer(ITIMER_REAL,&val,0);

    while(1)
    {
        printf("AAAAA\n");
        sleep(1);
    }
    return 0;
}

3秒钟过后每隔1秒钟显示 “起床了”。