进程定义为程序执行的一个实例。一个可执行程序执行起来就是一个进程,再执行起来一次它就又是一个进程,多个进程可以共享同一个可执行文件。
在一个进程中,可以用 fork() 创建一个子进程,当该子进程创建时,它从 fork() 指令的下一条(或者说从 fork() 的返回处)开始执行与父进程相同的代码。也就是说,fork() 函数产生了一个和当前进程完全一样的新进程,并和当前进程一样从 fork() 函数里返回,即原来一条执行通路(父进程),现在变成两条(父进程 + 子进程)。
fork() 之后,是父进程 fork() 之后的代码先执行还是子进程 fork() 之后的代码先执行是不一定的,这个跟内核调度算法有关。
#include
#include
#include
#include
// 信号处理函数
void sig_usr(int signo)
{
printf("收到了SIGUSR1信号,进程id=%d!\n", getpid());
}
int main(int argc, char* const* argv)
{
pid_t pid;
printf("进程开始执行!\n");
// 系统函数,第一个参数是个信号,第二个参数是个函数指针,代表一个针对该信号的捕捉处理函数
if (signal(SIGUSR1, sig_usr) == SIG_ERR)
{
printf("无法捕捉SIGUSR1信号!\n");
exit(1);
}
pid = fork(); // 创建一个子进程
// 要判断子进程是否创建成功
if (pid < 0)
{
printf("子进程创建失败,很遗憾!\n");
exit(1);
}
// 现在父进程和子进程同时开始运行了
for (;;)
{
sleep(1);
printf("休息1秒,进程id=%d!\n", getpid());
}
printf("再见了!\n");
return 0;
}

fork() 产生新进程的速度非常快,fork() 产生的新进程并不复制原进程的内存空间,而是和原进程(父进程)一起共享一个内存空间,但这个内存空间的特性是“写时复制”,也就是说,原来的进程和 fork() 出来的子进程可以同时自由地读取内存,但如果子进程或者父进程对内存进行修改的话,那么这个内存就会复制一份给该进程单独使用,以免影响到共享这个内存空间的其他进程使用。
fork() 会返回两次,父进程中返回一次,子进程中返回一次,而且 fork() 在父进程中返回的值和在子进程中返回的值是不同的,子进程的 fork() 返回值是
0
0
0,父进程的 fork() 返回值是新建立的子进程的 PID。在下面代码中,因为全局量 g_mygbltest 的值发生改变,导致父、子进程内存被单独分开,所以每个的 g_mygbltest 值也不同。
#include
#include
#include
#include
int g_mygbltest = 0;
int main(int argc, char* const* argv)
{
pid_t pid;
printf("进程开始执行!\n");
pid = fork(); // 创建一个子进程
// 要判断子进程是否创建成功
if (pid < 0)
{
printf("子进程创建失败,很遗憾!\n");
exit(1);
}
// 走到这里,fork()成功,执行后续代码的可能是父进程,也可能是子进程
if (pid == 0)
{
// 这里是子进程,因为子进程的fork()返回值是0,下面是专门针对子进程的处理代码
while (1)
{
g_mygbltest++;
sleep(1);
printf("真是太高兴了,我是子进程的,我的进程id=%d,g_mygbltest=%d!\n", getpid(), g_mygbltest);
}
}
else
{
// 这里是父进程,因为父进程的fork()返回值大于0(实际返回的是子进程的PID),下面是专门针对父进程的处理代码
while (1)
{
g_mygbltest++;
sleep(5);
printf("......,我是父进程的,我的进程id=%d,g_mygbltest=%d!\n", getpid(), g_mygbltest);
}
}
return 0;
}

#include
#include
#include
#include
int main(int argc, char* const* argv)
{
// 我们假定fork()都会成功,所以不判断返回值了
fork();
fork();
for (;;)
{
sleep(1);
printf("休息1秒,进程id=%d!\n", getpid());
}
printf("再见了!\n");
return 0;
}

#include
#include
#include
#include
int main(int argc, char* const* argv)
{
// 我们假定fork()都会成功,所以不判断返回值了
((fork() && fork()) || (fork() && fork()));
for (;;)
{
sleep(1);
printf("休息1秒,进程id=%d!\n", getpid());
}
printf("再见了!\n");
return 0;
}
|| 或运算:有
1
1
1 出
1
1
1,全
0
0
0 出
0
0
0;
&& 与运算:全
1
1
1 出
1
1
1,有
0
0
0 出
0
0
0;
|| 和 && 这两个运算具有短路特性。


系统中进程太多。
缺省情况,最大的PID为 32767。
如下图所示,每个用户有个允许开启的进程总数为 7774。
#include
#include
#include
#include
int main(int argc, char* const* argv)
{
printf("每个实际用户ID的最大进程数=%ld\n", sysconf(_SC_CHILD_MAX));
return 0;
}
