Linux 进程的基本控制—atexit、on_exit函数、文件锁

进程的基本控制:

     

进程控制函数:pause、sleep、usleep

 

函数atexit  on_exit

 

atexit函数:

    #include<stdlib.h>

     功能:注册终止函数(即进程执行结束后调用的函数)

     用法:int atexit( void (*func)(void)); (参数为回调函数)

     注意:按照ISO C的规定,一个进程可以登记多达32个函数,这些函数将由exit自动调用。atexit()注册的函数类型应为不接受任何参数的void函数,exit调用这些注册函数的顺序与它们登记时候的顺序相反。同一个函数如若登记多次,则也会被调用多次

 

例子:

 

#include<stdio.h>

#include<stdlib.h>

 

voidfunc()

{

       printf(“over\n”);

}

 

voidmain()

{

      atexit(func);

      printf(“进程:\n”);

 

}

 

运行结果:

进程:

over

 

说明:在进程结束时,会自动调用atexit函数的参数的回调函数,我们可以在这个回调函数中做一些操作,比如释放一些资源。

 

例子2:

 

 

 

#include<stdio.h>

#include<stdlib.h>

 

voidfun1()

{

    printf(“fun1被调用!\n”);

}

 

voidfun2()

{

    printf(“fun2被调用!\n”);

}

 

voidfun3()

{

    printf(“fun3被调用!\n”);

}

 

intmain()

{

atexit(fun1);

atexit(fun2);

atexit(fun3);

printf(“进程结束!\n”);

 

 

}

 

运行结果:

进程结束!

fun3被调用!

fun2被调用!

fun1被调用!

 

说明:进程结束所调用的回调函数,与其注册的顺序相反。

 

on_exit函数:

on_exit()函数式atexit函数的扩展

表头文件 #include<stdlib.h>   

定义函数 int on_exit(void (* function)(int, void*),void *arg);

 

参数arg 指针会传给参数function函数

function 的第一个参数是进程结束的返回码,第二个void指针参数为从on_exit函数中的参数arg传过来的。

返回值 如果执行成功则返回0,否则返回-1,失败原因存于errno中  

 

 

例子:

 #include<stdlib.h>
  void my_exit(int status,void *arg)
  {
         printf(“before exit()!\n”);
         printf(“exit (%d)\n”,status);
         printf(“arg = %s\n”,(char*)arg);

}

main()
{
 char * str=”test”;
  on_exit(my_exit,(void*)str);

exit(12);

}
执行
before exit()!
exit (12)

arg = test

 

 

 

进程与文件锁:

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

       问题:

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

       解决方案:

              文件锁(建议锁)

       API函数:

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

       编程技巧:

                对文件加锁

                判断一个文件是否存在锁

       函数说明:

                int fcntl(

                       int fd,//被加锁的文件描述符

                       int cnd,//加锁方式:F_SETLK(已经加锁则返回异常) F_SETLKW(已经加锁,堵塞等在,直到它减锁)F_UNLK

struct flock *lk);//锁的描述

                返回值:

                       0:加锁成功

                      -1:加锁失败

 

结构体flock的指针:
struct flcok 

short int l_type; /* 锁定的状态*/

//以下的三个参数用于分段对文件加锁,若对整个文件加锁,则:l_whence=SEEK_SET, l_start=0, l_len=0
short int l_whence; /*决定l_start位置*/ 
off_t l_start; /*锁定区域的开头位置*/ 
off_t l_len; /*锁定区域的大小*/

pid_t l_pid; /*锁定动作的进程*/ 
};

l_type 有三种状态: 
F_RDLCK   建立一个供读取用的锁定 
F_WRLCK   建立一个供写入用的锁定 
F_UNLCK   删除之前建立的锁定

_whence 也有三种方式: 
SEEK_SET   以文件开头为锁定的起始位置 
SEEK_CUR   以目前文件读写位置为锁定的起始位置 
SEEK_END   以文件结尾为锁定的起始位置

 

 

 

案例:

写两个程序:

                            A:加锁

                            B:获取锁的信息

 

1.       加锁程序

Setlock.c

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<fcntl.h>

 

void  main()

{

      int fd;

      struct flock  lk;

      int r;

      //打开文件

      fd=open(“text.txt”,O_RDWR);

     if(fd==0)

     {

           printf(“open error:%m\n”);

           exit(-1);

     }

     //描述锁

lk.l_type=F_RDWR;

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);   //加个死循环为使进程不退出,程序退出后自动减锁

}

 

2.       获取锁的信息:

Getlock.c

 

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<fcntl.h>

 

 

void main()

{

int fd;

      struct flock  lk;

      int r;

      //打开文件

      fd=open(“text.txt”,O_RDWR);

     if(fd==0)

     {

           printf(“open error:%m\n”);

           exit(-1);

     }

     //获取锁的信息:

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

  if(r==0)

{

    printf(“得到锁成功!\n”);

   if(lk.l_type==F_RDWR)

    {

         printf(“写锁\n”);

    }

}

else

{

    printf(“得到锁失败!\n”);

}

 

 

 

}

 

结论:锁也是一个进程共享的信息

   

你可能感兴趣的:(c,linux,进程控制,文件锁,atexit)