Linux信号机制代码示例

1 基本功能
本Blog创建了两个进程(父子进程):

  • 父进程
    执行文本复制操作,当收到 SIGUSR1信号后,打印出现在文件复制的进度;
  • 子进程
    每个固定时间段向父进程发送一个 SIGUSR1 信号。

2 代码示例

/*
 * File: Signal.c
 *Description: Two process
    1. Father:  copy a file, when receive the SIGUSR1 signal, print the progress
    2. Child: timing trigger the parent process
 *Autor: Jimmy Nie
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <sys/fcntl.h>

void handler(int sig);
void SigAlarm(int sig);

int count = 0;      //has read bytes
int fileSize = 0;   //the source file size

int main(int argc, char *argv[])
{
    //variable define
    int fd_src, fd_dst;
    int tmp = 0;        //how many bytes read every time
    char buf[128] ;      //tempature storage buffer

    //0. check the argument
    if(argc != 3)
    {
        printf("%s(%d): Check the arguments, argument=%d(3 is need)
", argc);
        exit(EXIT_FAILURE);
    }

    //1. open the file
    if(-1 == (fd_src=open(argv[1], O_RDONLY)))
    {
        perror("open");
        exit(EXIT_FAILURE);
    }

    //open the destination file, if it does not exist, creat it first
    if(-1 == (fd_dst=open(argv[2], O_RDWR|O_CREAT, 0644)))
    {
        perror("open");
        exit(EXIT_FAILURE);
    }

    //2. Obtain the source file size
    fileSize = lseek(fd_src, 0, SEEK_END);
    if(fileSize < 0)
    {
        perror("lseek");
        exit(EXIT_FAILURE);
    }
    
     lseek(fd_src, 0, SEEK_SET);

    //3. Father process install SIGUSR1 signal
    if(signal(SIGUSR1, handler) == SIG_ERR)
    {
        perror("signal");
        exit(EXIT_FAILURE);
    }

    //4. Creat a new process(child)
    pid_t  pid;
    if(-1 == (pid=fork()))
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    //In child process
    else if(pid == 0)
    {
        //Install the signal SIGALRM
        if(signal(SIGALRM, SigAlarm) == SIG_ERR)
        {
            perror("signal");
            exit(EXIT_FAILURE);
        }

        ualarm(200,10000);  //after 20ms start trigger, and every 50ms trigger once
        //alarm(1);

        while(1)    //execute continues
            ;
    }

    //In parent process
    else
    {
        //3. copy source file to destination file
        while(1)
        {
            //read the source file to buf
            if(-1 == (tmp=(read(fd_src, buf, 128))))
            {
                perror("read");
                exit(EXIT_FAILURE);
            }

            //check the end of file
            if(0 == tmp)
            {
                printf("Finished copy the file, and file size:%d
", fileSize);
                kill(pid, SIGINT);      //finished copy, trigger a signal to child, and terminate child process
                break;
            }

            //write the buffer to the destination file
            if(-1 == write(fd_dst, buf, tmp))
            {
                perror("Write");
                exit(EXIT_FAILURE);
            }

            count += tmp;
        }

        wait(NULL);     //wait child process exit
        close(fd_src);
        close(fd_dst);
    }


    return 0;
}

//function used to print the progree of copy file
void handler(int sig)
{
    int i = 0;
    i = (int)(((float)count / (float)fileSize) * 100);
    printf("
Has copyed %d%% 
",i);

    int j = 0;
    for(j=0; j<i; j++)
    {
        if(j%2)
            printf("*");
    }

    printf("
");
}

//used to send SIGUSR1 signal to parent process
void SigAlarm(int sig)
{
    kill(getppid(), SIGUSR1);
    //alarm(1);
}

编译该代码:


[root@niesh Linux]# gcc -o signal signal.c
[root@niesh Linux]# ll
总用量 36
-rwxrwxr-x. 1 niesh niesh  8659 9月  22 22:07 produce
-rw-rw-r--. 1 root  niesh   467 9月  22 22:07 produce.c
-rwxr-xr-x. 1 root  root  13445 9月  23 11:26 signal
-rw-rw-r--. 1 root  niesh  3407 9月  22 22:45 signal.c

但是此时我们还需要一个大于1M的ASCII文件,使得CP不至于瞬间完成:

#include <stdio.h>
#include <sys/fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int fd;
    int count = 0;
    char buf[] = "Hello,world
";

    fd = open(argv[1], O_RDWR|O_CREAT, 0644);
    
    for(count=0; count < 1024*1024; count++)
        write(fd, buf, strlen(buf));        //file size = 16*256*1024*1024 = 4Mbyte

    //printf("The sizeof(buf)=%d
",sizeof(buf));
    close(fd);

    return 0;
}

通过以上代码我们可以产生出一个12M的文本文件:


[root@niesh Linux]# gcc -o produce produce.c
[root@niesh Linux]# ./produce test
[root@niesh Linux]# ll -h
总用量 13M
-rwxr-xr-x. 1 root root  8.5K 9月  23 11:31 produce
-rw-rw-r--. 1 root niesh  467 9月  22 22:07 produce.c
-rwxr-xr-x. 1 root root   14K 9月  23 11:26 signal
-rw-rw-r--. 1 root niesh 3.4K 9月  22 22:45 signal.c
-rw-r--r--. 1 root root   12M 9月  23 11:31 test            //ASCII文件 12M

3 执行效果


[root@niesh Linux]# ./signal test t1

Has copyed 1%


Has copyed 3%
*

Has copyed 6%
***

Has copyed 7%
***

Has copyed 9%
****

Has copyed 10%
*****

Has copyed 15%
*******

Has copyed 21%
**********

Has copyed 25%
************

Has copyed 29%
**************

Has copyed 34%
*****************

Has copyed 42%
*********************

Has copyed 44%
**********************

Has copyed 48%
************************

Has copyed 54%
***************************

Has copyed 58%
*****************************

Has copyed 65%
********************************

Has copyed 71%
***********************************

Has copyed 76%
**************************************

Has copyed 80%
****************************************

Has copyed 88%
********************************************

Has copyed 93%
**********************************************

Has copyed 97%
************************************************
Finished copy the file, and file size:12582912

查看复制后的结果:


[root@niesh Linux]# ll -h
总用量 25M
-rwxr-xr-x. 1 root root  8.5K 9月  23 11:31 produce
-rw-rw-r--. 1 root niesh  467 9月  22 22:07 produce.c
-rwxr-xr-x. 1 root root   14K 9月  23 11:26 signal
-rw-rw-r--. 1 root niesh 3.4K 9月  22 22:45 signal.c
-rw-r--r--. 1 root root   12M 9月  23 11:42 t1                //复制后生成的文件
-rw-r--r--. 1 root root   12M 9月  23 11:31 test

原文地址:https://www.cnblogs.com/Jimmy1988/p/7580701.html