做网站学不需要做后台管理系统,阿里云用什么系统做网站好,个人做论坛网站怎么做,深圳华强北做网站0202 Linux进程资源 专栏内容#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页#xff1a;我的主页 管理社区#xff1a;开源数据库 座右铭#xff1a;天行健#xff0c;君子以自强不息#xff1b;地势坤#xff0c;君子以厚德载物. 文章目录 020…0202 Linux进程资源 专栏内容 postgresql使用入门基础手写数据库toadb并发编程 个人主页我的主页 管理社区开源数据库 座右铭天行健君子以自强不息地势坤君子以厚德载物. 文章目录 0202 Linux进程资源一、概述 二、资源创建场景 三、资源在子进程中创建 3.1 示例代码 3.2 进程独立验证 四、程序启动时资源创建 4.1 示例代码 4.2 共用内核对象 总结 结尾 一、概述 进程启动之后除了占用内存资源之外在进程中还会打开文件共享内存网络套接字等与内核对象关联的资源
这些资源在子进程中如何处理呢
本节以文件为例分析父子进程间对于与内核相关联的资源的处理情况并使用代码实例进行演示。
二、资源创建场景 在使用fork创建子进程的时刻对资源的使用大致分为两类情况
也可能是运行了一段程序初始化很多资源然后再创建多进程任务 此时子进程会继承父进程创建的资源 同时要在子进程中关闭和释放不再使用的资源否则会产生资源泄漏 也可能是刚开始运行先创建多任务然后根据不同任务的分工不同再初始化各自的资源 此时各子进程中没有继承的资源 在第一类场景下对于关联内核对象的资源继承后的特性也会与单进程使用有一定区别下面通过案例来分析一下。
三、资源在子进程中创建 资源在fork之后创建也就是在子进程中创建。
这种情况与我们常规编写一个main函数中创建类似也就是单进程程序一样各子进程间互相独立没有联系。 3.1 示例代码
下面通过一段测试代码来演示一下
/** ex020104_forkafter.c*/
#include stdio.h#include sys/types.h
#include unistd.h#include errno.h
#include string.htypedef struct Info
{int pid;int seg;
}Info;FILE *fp NULL;
int segno 0;void OpenFile(char *path);
void CloseFile();
void ReadFile();
void WriteFile();int main(int argc ,char *argv[])
{int pid -1;pid fork();if(pid 0){OpenFile(test);// in child printf(here in child ,my pid is %d\n, getpid());WriteFile();sleep(5);WriteFile();sleep(5);WriteFile();}else if(pid 0){OpenFile(test);// in parentprintf(here in parent, my pid %d, child pid is %d\n, getpid(), pid);sleep(3);ReadFile();sleep(5);ReadFile();sleep(5);ReadFile();}else{// errorprintf(fork error[%s]\n,strerror(errno));}CloseFile();return 0;
}在创建子进程之后父子进程中同时打开test文件进行以下步骤
子进程从文件头写入结构体数据父进程从文件头读一个结构体大小的数据然后子进程在上次偏移位置继续写入结构体大小的数据接着父进程从自己的偏移位置处读入结构体数据继续一次步骤3和4在进程结束时关闭文件。
公共的文件操作函数
为了方便多次测试将打开文件关闭文件读写文件编写为公共函数。
void OpenFile(char *path)
{if(NULL path)return;fp fopen(path, w);if(NULL fp){printf(open file %s error!\n, path);}return;
}void CloseFile()
{if(NULL ! fp)fclose(fp);
}void ReadFile()
{Info rinfo {0};int pos 0;if(NULL fp)return ;/* data read from current position record by the fp. */pos ftell(fp);fread(rinfo, sizeof(rinfo), 1, fp); printf([%d] read from %d, context(%d, %d) \n, getpid(), pos, rinfo.pid, rinfo.seg);
}void WriteFile()
{Info winfo {0};int pos 0;if(NULL fp)return ;winfo.seg segno;winfo.pid getpid();/* data read from current position record by the fp. */pos ftell(fp);fwrite(winfo, sizeof(winfo), 1, fp); fflush(fp);printf([%d] write to %d, context(%d, %d) \n, getpid(), pos, winfo.pid, winfo.seg);
} 3.2 进程独立验证
编译运行
[senllanghatch ex_0201]$ gcc ex020104_forkafter.c -o extest
[senllanghatch ex_0201]$ ./extest
here in parent, my pid 802470, child pid is 802471
here in child ,my pid is 802471
[802471] write to 0, context(802471, 0)
[802470] read from 0, context(802471, 0)
[802471] write to 8, context(802471, 1)
[802470] read from 8, context(802471, 1)
[802471] write to 16, context(802471, 2)
[802470] read from 16, context(802471, 2)结果分析 可以看到进程802471从文件偏移为0处开始写入数据而父进程802470也是从偏移为0处读数据两个进程的偏移都是各自计数互相独立文件偏移记录在内核文件表项中 四、程序启动时资源创建 如果在程序启动时创建文件也就是在fork之前创建子进程会继承之前创建的文件句柄。 在这种情况下会出现什么样的情况呢 4.1 示例代码
/** ex020103_forkresource.c*/
#include stdio.h#include sys/types.h
#include unistd.h#include errno.h
#include string.htypedef struct Info
{int pid;int seg;
}Info;FILE *fp NULL;
int segno 0;void OpenFile(char *path);
void CloseFile();
void ReadFile();
void WriteFile();int main(int argc ,char *argv[])
{int pid -1;OpenFile(test);pid fork();if(pid 0){// in child printf(here in child ,my pid is %d\n, getpid());WriteFile();sleep(5);WriteFile();sleep(5);WriteFile();}else if(pid 0){// in parentprintf(here in parent, my pid %d, child pid is %d\n, getpid(), pid);sleep(3);ReadFile();sleep(5);ReadFile();sleep(5);ReadFile();}else{// errorprintf(fork error[%s]\n,strerror(errno));}CloseFile();return 0;
}这段代码与前例类似只是将创建文件放在了fork之前
也就是FILE *fp 在主程序中先被初始化了然后创建了子进程在子进程中引用了一模一样的内容类似于拷备了一份。 4.2 共用内核对象
编译运行
[senllanghatch ex_0201]$ gcc ex020103_forkresource.c -o extest1
[senllanghatch ex_0201]$ ./extest1
here in parent, my pid 803877, child pid is 803878
here in child ,my pid is 803878
[803878] write to 0, context(803878, 0)
[803877] read from 8, context(0, 0)
[803878] write to 8, context(803878, 1)
[803877] read from 16, context(0, 0)
[803878] write to 16, context(803878, 2)
[803877] read from 24, context(0, 0)可以看到很有意思的现象
在子进程803878中在文件偏移0处写入之后偏移变为8而之后父进程803877开始读时文件偏移为8并没有从0开始接着子进程803878又从偏移8处写入数据之后偏移变为16而父进程803877读偏移也变成了16后面一次也是父进程中文件偏移与子进程中文件偏移相互联系 总结 好了到这里子进程是父进程的拷贝有了更加深入的理解这里像编程语言中的深拷贝与浅拷贝的关系。
而子进程其实是做了一些浅拷贝引用的内核文件表项还是一份这就会引起两个进程共同操作的问题。
在这种情况下每次操作需要加锁同时要指定操作的位置和大小。
结尾 非常感谢大家的支持在浏览的同时别忘了留下您宝贵的评论如果觉得值得鼓励请点赞收藏我会更加努力 作者邮箱studysenllang.onaliyun.com 如有错误或者疏漏欢迎指出互相学习。
注未经同意不得转载