在fork是需要注意父进程中的哪些资源是会被子进程继承的
用于管理动态内存和文件描述符的RAII类可以正常工作
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h> // open
pid_t g_parent_pid = 0;
#define NEW_BUF_SIZE 6
// 子进程会继承地址空间和文件描述符
struct A
{
char *m_pBuf; //动态内存
int m_fd; // 文件描述符会被子进程继承
A()
{
m_pBuf = new char[NEW_BUF_SIZE] {0};
char buf[] = "hello";
strcpy(m_pBuf, buf);
m_fd = open("./test.txt", O_RDWR | O_CREAT, 0666);
printf("A() , pBuf:%p, m_fd=%d\n", m_pBuf, m_fd);
}
~A()
{
printf("pid=%d, ~A(), pBuf:%p, m_fd=%d, m_pBuf:%s\n", getpid() , m_pBuf, m_fd, m_pBuf);
bzero(m_pBuf, NEW_BUF_SIZE);
delete m_pBuf;
m_pBuf = nullptr;
close(m_fd);
}
void dosomething()
{
if(g_parent_pid == getpid())
{
sleep(5);
}
char buf[] = "hello";
write(m_fd, buf, sizeof(buf) );
printf("pid:%d, do something...., m_fd=%d, m_pBuf=%s\n", getpid(), m_fd, m_pBuf);
strcpy(m_pBuf, "hello world");
}
};
int main()
{
A a ;
printf("i'm parent process!\n");
g_parent_pid = getpid();
pid_t pid = fork();
a.dosomething();
printf("i'm very happy.\n");
return 0; // ~A() 被调用了两次: 父进程和子进程各一次
}
注意子进程不会继承:
- 父进程的内存锁:
mlock(2)
,mlockall(2)
- 父进程的文件锁:
fcntl(2)
, 但是会继承fcntl(2)打开的文件文件 和
父进程中的flock(2)
- 父进程的某些定时器:
settimer(2), alarm(2), timer_create(2)
- pending signal (
sigpending(2)
) - 信号量(
semop(2)
) - CPU计数器
- 异步IO操作(
aio_read(3)
,aio_write(3)
, 和 异步IO的context
思考: 下面程序一共有多少个进程(包括main进程)?
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
fork();
fork() && fork() || fork();
fork();
// g_num ++ ;
// printf("num =%d\n", g_num);
// 此处会阻塞等待输入, 此时可以在另外的终端通过以下命令查看
// ps aux | grep a.out | grep -v grep | wc -l
getchar();
return 0;
}
// int g_num = 0;
// pid_t myfork()
// {
// pid_t pid = fork();
// if(0 == pid )
// {
// printf("=\n");
// }
// return pid;
// }
// int main()
// {
// myfork();
// myfork() && myfork() || myfork();
// myfork();
// g_num ++ ;
// // printf("num =%d\n", g_num);
// return 0;
// }
// fork() && fork() || fork();
/*
pid = fork()
if(pid > 0)
{
if(0 == fork() )
{
fork()
}
}
else if(pid == 0)
{
fork()
}
*/