程序陷入while循环
Program stuck in while loop
我试图在 while 循环中使用信号量,但我的程序 运行 处于无限循环中。基本上我 fork off children 并使用 execv 来启动新的用户进程。进程使用共享内存中的信号量进行通信。
struct shared
{
int count;
sem_t sem;
} *shmem;
void forking()
{
key_t shmkey = ftok("makefile",777);
if (shmkey == -1) {
perror("Ftok failed");
exit(-1);
}
// Get our shm id
shmid = shmget(shmkey, sizeof(shared), 0666 | IPC_CREAT);
if (shmid == -1) {
perror("Failed to allocate shared memory region");
exit(-1);
}
// Attach to our shared memory
shmem = (shared*)shmat(shmid, (void *)0, 0);
if (shmem == (void *)-1) {
perror("Failed to attach to shared memory region");
exit(-1);
}
sem_init(&(shmem->sem),1,1);
pid_t PID;
int i;
for(i=0;i<4;i++)
{
PID=fork();
if(PID==0)
{
static char *args[]={"./child",NULL};
int status;
if(( status= (execv(args[0], args)))==-1)
perror("failed to execv");
exit(EXIT_FAILURE);
}
if(PID>0)
{
while(1)
{
sem_wait(&(shmem->sem));
{
shmem->count=shmem->count+1;
}
sem_post(&(shmem->sem));
}
}
if(PID<0)
perror("error in fork");
}
}
main()
{
forking();
}
在child.c
struct shared
{
int count;
sem_t sem;
} shmem;
void main()
{
bool alive=true;
do
{
sem_wait(&(shmem->sem));
if(shmem->count==5)
{
shmem->count=0;
alive=false;
}
sem_post(&(shmem->sem));
}while(alive);
}
child.c 无休止地循环,不允许父级将 i 递增到 5。即使我在第一个文件中注释掉 while 循环并让它在没有 loops.In 的情况下递增,也会发生这种情况。结束没有任何退出。
你用错了fork,绝对不是用共享内存。
这里有几点
- 通过调用 fork,您将在不同的内存 space 中复制 parent 运行。 http://man7.org/linux/man-pages/man2/fork.2.html
- 通过使用 execve,您实际上删除了旧内存并将其替换为新内存,而新内存无论如何都没有链接到您的 parent 进程。 http://man7.org/linux/man-pages/man2/execve.2.html
为了让你的代码工作,你应该使用 pthread_*
而不是因为它将存在于相同的内存中 space 并使你的全局变量 volatile 因为 gcc 将尝试优化并且会有奇怪的行为如果这样做的话。
好吧,我似乎错过了很多要点,但我的假设并非完全错误。
所以你的 child.c 少了很多代码
- 它不包含您在 parent 中所做的所有初始化,这是必要的,因为如果您使用
execve
,您基本上会丢失之前在 [=] 中映射的所有内存映射45=]进程。
- 你的 parents 无限循环所以
shmem->count
永远不会真正等于 5,你将不得不在某个时刻中断或改变你的 child 代码中的条件。
这是您的 child 的样子。
#include <semaphore.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct
{
int count;
sem_t sem;
} shared;
shared *shmem;
int shmid;
key_t shmkey;
int main()
{
int alive=1;
shmkey = ftok("makefile",777);
if (shmkey == -1) {
perror("Ftok failed");
exit(-1);
}
// Get our shm id
shmid = shmget(shmkey, sizeof *shmem, 0);
if (shmid == -1) {
perror("Failed to allocate shared memory region");
exit(-1);
}
// Attach to our shared memory
shmem = (shared*)shmat(shmid, (void *)0, 0);
if (shmem == (shared *)-1) {
perror("Failed to attach to shared memory region");
exit(-1);
}
do
{
sem_wait(&(shmem->sem));
printf("%d\n", shmem->count);
if(shmem->count > 5)
{
shmem->count=0;
alive=0;
}
sem_post(&(shmem->sem));
}while(alive);
printf("I have finished %u\n", getpid());
exit(0);
}
我试图在 while 循环中使用信号量,但我的程序 运行 处于无限循环中。基本上我 fork off children 并使用 execv 来启动新的用户进程。进程使用共享内存中的信号量进行通信。
struct shared
{
int count;
sem_t sem;
} *shmem;
void forking()
{
key_t shmkey = ftok("makefile",777);
if (shmkey == -1) {
perror("Ftok failed");
exit(-1);
}
// Get our shm id
shmid = shmget(shmkey, sizeof(shared), 0666 | IPC_CREAT);
if (shmid == -1) {
perror("Failed to allocate shared memory region");
exit(-1);
}
// Attach to our shared memory
shmem = (shared*)shmat(shmid, (void *)0, 0);
if (shmem == (void *)-1) {
perror("Failed to attach to shared memory region");
exit(-1);
}
sem_init(&(shmem->sem),1,1);
pid_t PID;
int i;
for(i=0;i<4;i++)
{
PID=fork();
if(PID==0)
{
static char *args[]={"./child",NULL};
int status;
if(( status= (execv(args[0], args)))==-1)
perror("failed to execv");
exit(EXIT_FAILURE);
}
if(PID>0)
{
while(1)
{
sem_wait(&(shmem->sem));
{
shmem->count=shmem->count+1;
}
sem_post(&(shmem->sem));
}
}
if(PID<0)
perror("error in fork");
}
}
main()
{
forking();
}
在child.c
struct shared
{
int count;
sem_t sem;
} shmem;
void main()
{
bool alive=true;
do
{
sem_wait(&(shmem->sem));
if(shmem->count==5)
{
shmem->count=0;
alive=false;
}
sem_post(&(shmem->sem));
}while(alive);
}
child.c 无休止地循环,不允许父级将 i 递增到 5。即使我在第一个文件中注释掉 while 循环并让它在没有 loops.In 的情况下递增,也会发生这种情况。结束没有任何退出。
你用错了fork,绝对不是用共享内存。
这里有几点
- 通过调用 fork,您将在不同的内存 space 中复制 parent 运行。 http://man7.org/linux/man-pages/man2/fork.2.html
- 通过使用 execve,您实际上删除了旧内存并将其替换为新内存,而新内存无论如何都没有链接到您的 parent 进程。 http://man7.org/linux/man-pages/man2/execve.2.html
为了让你的代码工作,你应该使用 pthread_*
而不是因为它将存在于相同的内存中 space 并使你的全局变量 volatile 因为 gcc 将尝试优化并且会有奇怪的行为如果这样做的话。
好吧,我似乎错过了很多要点,但我的假设并非完全错误。
所以你的 child.c 少了很多代码
- 它不包含您在 parent 中所做的所有初始化,这是必要的,因为如果您使用
execve
,您基本上会丢失之前在 [=] 中映射的所有内存映射45=]进程。 - 你的 parents 无限循环所以
shmem->count
永远不会真正等于 5,你将不得不在某个时刻中断或改变你的 child 代码中的条件。
这是您的 child 的样子。
#include <semaphore.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct
{
int count;
sem_t sem;
} shared;
shared *shmem;
int shmid;
key_t shmkey;
int main()
{
int alive=1;
shmkey = ftok("makefile",777);
if (shmkey == -1) {
perror("Ftok failed");
exit(-1);
}
// Get our shm id
shmid = shmget(shmkey, sizeof *shmem, 0);
if (shmid == -1) {
perror("Failed to allocate shared memory region");
exit(-1);
}
// Attach to our shared memory
shmem = (shared*)shmat(shmid, (void *)0, 0);
if (shmem == (shared *)-1) {
perror("Failed to attach to shared memory region");
exit(-1);
}
do
{
sem_wait(&(shmem->sem));
printf("%d\n", shmem->count);
if(shmem->count > 5)
{
shmem->count=0;
alive=0;
}
sem_post(&(shmem->sem));
}while(alive);
printf("I have finished %u\n", getpid());
exit(0);
}