进程的基本控制:
进程控制函数: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”);
}
}
结论:锁也是一个进程共享的信息