一、如何创建进程?
linux通过fork()系统调用创建新一个进程,老进程叫父进程,复制生成的新进程叫子进程。父子关系是相对的,每一代都有一个父子关系。
fork函数定义如下:
#include <unistd.h>
pid_t fork(void);
实例1:
#include <unistd.h>
#include <stdio.h>
int main (void)
{
pid_t fpid = -1; //fpid表示fork函数返回的值
printf("this is fork test.\r\n");
fpid=fork();
if (fpid < 0){
printf("error in fork!\r\n");
} else if (fpid == 0){//子进程
printf("\r\n");
printf("fpid is %d\r\n",fpid);
printf("child process, my PID is %d\r\n",getpid());
printf("child process, my PPID is %d\r\n",getppid());
} else if (fpid > 0){//父进程
printf("\r\n");
printf("fpid is %d\r\n",fpid);
printf("parent process, my PID is %d\r\n",getpid());
printf("parent process, my PPID is %d\r\n",getppid());
}
printf("hello world, pid = %d.\r\n", getpid());
return 0;
}
fork的原理:当一个进程A调用fork时,系统内核创建一个新的进程B,并将A的内存映像复制到B的进程空间中,因为A和B是一样的,那么他们怎么知道自己是父进程还是子进程呢,看fork的返回值就知道,上面的实验结果也能看出:fork在子进程中返回0,在父进程中返回子进程的pid。
二、父子进程对文件的操作
1.子进程继承父进程中打开的文件
父进程以O_TRUNC的方式打开文件,后续和子进程对文件进行写入
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
// 首先打开一个文件
int fd = -1;
pid_t pid = -1;
fd = open("1.txt", O_RDWR | O_TRUNC);
if (fd < 0)
{
perror("open");
return -1;
}
// fork创建子进程
pid = fork();
if (pid > 0)
{
// 父进程中
printf("parent.\r\n");
write(fd, "hello", 5);
Sleep(1);//给系统调度充足的时间
}
else if (pid == 0)
{
// 子进程
printf("child.\r\n");
write(fd, "world", 5);
Sleep(1);//给系统调度充足的时间
}
else
{
perror("fork");
exit(-1);
}
close(fd);
return 0;
}
2、父子进程各自独立打开同一文件实现共享
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
// 首先打开一个文件
int fd = -1;
pid_t pid = -1;
// fork创建子进程
pid = fork();
if (pid > 0)
{
// 父进程中
fd = open("1.txt", O_RDWR );
if (fd < 0)
{
perror("open");
return -1;
}
printf("parent.\n");
write(fd, "hello", 5);
sleep(1);
}
else if (pid == 0)
{
// 子进程
fd = open("1.txt", O_RDWR );
if (fd < 0)
{
perror("open");
return -1;
}
printf("child.\n");
write(fd, "world", 5);
sleep(1);
}
else
{
perror("fork");
exit(-1);
}
close(fd);
return 0;
}
结果都是world,原因如下表,父子进程文件描述符所指向的文件表是独立的。当父进程先执行的时候,写入了hello,子进程执行的时候,由于文件表独立,所以文件指针也独立,子进程是从0偏移地址写,所以会将之前写的hello覆盖掉,只剩下world。
要想实现接续写的效果,只需在open时使用O_APPEND
原因:如果用O_APPEND标志打开一个文件,则相应标志也被设置到文件表项的文件状态标志中. 每次对这种具有追加写标志的文件执行写操作时,文件表项中的当前文件偏移量首先会被设置为i节点表项中的文件长度,这就使得每次写入的数据都追加到文件的当前尾端处.