一直以来,我都认为在Linux下使用fork创建的新的进程和父进程具有相同的代码段和相同的全局数据段,但是今天遇到了一点问题!!!!
例程:使用父子进程共同打印一段字符串,子进程打印前半,父进程后半,时间间隔1s,初步源码如下:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int i,j;
pid_t pid;
const char *message="this is a test string\n";
int n = strlen(message) / 2;
pid = fork();
j = (pid == 0 ? 0 : n);
for ( i = 0; i < n; i++)
{
write(STDOUT_FILENO,message + i + j,1);
sleep(1);
}
return 0;
}
//运行结果混乱。因为涉及到同步的的问题,所以使用信号量来解决,代码如下:#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
int main()
{
int i,j;
pid_t pid;
const char *message="this is a test string\n";
int n = strlen(message) / 2;
sem_t sem;
sem_init(&sem,2,0);pid = fork();j = (pid == 0 ? 0 : n);
if(pid > 0)
{
sem_wait(&sem);
}
for ( i = 0; i < n; i++)
{
write(STDOUT_FILENO,message + i + j,1);
sleep(1);
}
if(pid == 0)
{
sem_post(&sem);
}
sem_destroy(&sem);
return 0;
}
//结果子进程正常打印,父进程一直等待获取信号量的位置。
十分不解,使用gdb调试后发现,在子进程中出现的效果和自己设想的一样(即:sem.__align的值+1),按理说这样后父进程能够获取到信号量才对。。。很明显了,父子进程的地址空间的虚拟地址一样,但是指向的数据区域的实际物理地址不一样。。。。
然后稍微的改了一下程序,将sem_t sem;定义为全局变量,但是结果依旧。。子进程仍然无法改变父进程的地址空间中的值。
然后就将无名信号改成了有名信号:程序如下:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
//static sem_t sem;
int main()
{
int i,j;
pid_t pid;
const char *message="this is a test string\n";
int n = strlen(message) / 2;
sem_t *sem;
sem = sem_open("/sem", O_CREAT, S_IRUSR | S_IWUSR, 0);
pid = fork();
j = (pid == 0 ? 0 : n);
if(pid > 0)
{
sem_wait(sem);
}
for ( i = 0; i < n; i++)
{
write(STDOUT_FILENO,message + i + j,1);
sleep(1);
}
if(pid == 0)
{
sem_post(sem);
}
sem_destroy(sem);
return 0;
}
//得到了预期结果
然后。。。。突然醒悟。。。。
如果父子进程能够直接共享局部变量和全局变量数据,还用管道、共享内存……干嘛。。。。
本文探讨了在Linux环境下使用fork创建子进程时遇到的同步问题,并通过具体示例介绍了如何利用信号量解决进程间的资源竞争问题。
1007

被折叠的 条评论
为什么被折叠?



