我有以下程序,但无法使其在客户端和服务器之间正确同步。 运行后,我的程序总是在客户端和试图进入临界区的服务器之间发生冲突。 正如您将看到的,我使用带有共享内存的 systemV 信号量,以便进程相互通信。
我做错了什么?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#define SHM_SIZE 1024 // make it a 1K shared memory segment
#define MAX_FILES 10
#define MAX_LINES 10
/* Union semun */
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* array for GETALL, SETALL */
};
// Semaphore operations
struct sembuf wait_server = {0, -1, SEM_UNDO};
struct sembuf signal_server = {0, 1, SEM_UNDO};
struct sembuf wait_client = {1, -1, SEM_UNDO};
struct sembuf signal_client = {1, 1, SEM_UNDO};
// Shared data structure between threads
struct SharedData {
char shared_memory[SHM_SIZE];
int start_line;
int end_line;
int file_index;
int max_requests;
int client_request; // Store the client's request number
};
void free_resources(int shm_id, int sem_id) {
/* Delete the shared memory segment */
shmctl(shm_id, IPC_RMID, NULL);
/* Delete the semaphores */
semctl(sem_id, 0, IPC_RMID, 0);
semctl(sem_id, 1, IPC_RMID, 0);
}
/* Semaphore P - down operation, using semop */
int sem_P(int sem_id, int sem_num) {
struct sembuf sem_d;
sem_d.sem_num = sem_num;
sem_d.sem_op = -1;
sem_d.sem_flg = 0;
if (semop(sem_id, &sem_d, 1) == -1) {
perror("# Semaphore down (P) operation ");
return -1;
}
return 0;
}
/* Semaphore V - up operation, using semop */
int sem_V(int sem_id, int sem_num) {
struct sembuf sem_d;
sem_d.sem_num = sem_num;
sem_d.sem_op = 1;
sem_d.sem_flg = 0;
if (semop(sem_id, &sem_d, 1) == -1) {
perror("# Semaphore up (V) operation ");
return -1;
}
return 0;
}
/* Semaphore Init - set a semaphore's value to val */
int sem_Init(int sem_id, int sem_num, int val) {
union semun arg;
arg.val = val;
if (semctl(sem_id, sem_num, SETVAL, arg) == -1) {
perror("# Semaphore setting value ");
return -1;
}
return 0;
}
int main(int argc, char *argv[]) {
// Passing arguments to variables
int N = atoi(argv[1]); // Number of clients
int K = atoi(argv[2]); // Total number of files
int L = atoi(argv[3]); // Number of requests per client
int shm_id;
int sem_id;
struct SharedData *data;
int pid;
/* Create a new shared memory segment */
shm_id = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0660);
if (shm_id == -1) {
perror("Shared memory creation");
exit(EXIT_FAILURE);
}
/* Create a new semaphore id */
sem_id = semget(IPC_PRIVATE, 2, IPC_CREAT | 0660);
if (sem_id == -1) {
perror("Semaphore creation ");
shmctl(shm_id, IPC_RMID, (struct shmid_ds *)NULL);
exit(EXIT_FAILURE);
}
/* Set the value of the semaphores to 0 */
if (sem_Init(sem_id, 0, 0) == -1 || sem_Init(sem_id, 1, 0) == -1) {
free_resources(shm_id, sem_id);
exit(EXIT_FAILURE);
}
/* Attach the shared memory segment */
data = (struct SharedData *)shmat(shm_id, NULL, 0);
if (data == NULL) {
perror("Shared memory attach ");
free_resources(shm_id, sem_id);
exit(EXIT_FAILURE);
}
data->max_requests = L;
int sleeptime;
// Register the signal handler for client finished
for (int i = 0; i < N; i++) {
/* New process */
sleeptime = random() % 10;
if ((pid = fork()) == -1) {
perror("fork");
free_resources(shm_id, sem_id);
exit(EXIT_FAILURE);
}
if (pid == 0) {
printf("# I am the child process with process id: %d\n", getpid());
int j = 0;
while (j < data->max_requests) {
/* Child process */
//sem_V(sem_id, 1); // Signal server to process the request
//sem_P(sem_id, 0); // Wait for server to finish
data->file_index = rand() % MAX_FILES + 1;
data->start_line = rand() % MAX_LINES + 1;
data->end_line = rand() % (MAX_LINES - data->start_line) + data->start_line;
printf("(%d): Client %d request %d\n", getpid(), i, j);
data->client_request = j+1; // Set the client's request number
sem_V(sem_id, 1); // Signal server to process the request
// Wait for the server to process the request
sem_P(sem_id, 0); // Wait for server to finish
printf("(%d): Server processed request %d\n", getpid(), j);
j++;
printf("j is %d \n ",j);
}
/* Child process */
exit(EXIT_SUCCESS);
} else {
/* Server process */
int j = 0;
while (j < data->max_requests) {
// sleep(5);
/* Wait for child process */
sem_V(sem_id, 0); // Signal client to continue
sem_P(sem_id, 1); // Wait for client to request
printf("# I am the server process with process id: %d\n", getpid());
// Process client requests here
printf("(%d): processing client requests\n", getpid());
// Example: Send a response to clients through shared memory
strcpy(data->shared_memory, "Response from server");
j++;
}
wait(NULL);
}
}
// Clear resources
free_resources(shm_id, sem_id);
return 0;
}
信号量代码不是问题。没关系。
问题出在这一行:
data->end_line = rand() % (MAX_LINES - data->start_line) + data->start_line;
它有时会导致除以零(只是不是立即)并产生
SIGFPE
。这将终止/中止子线程。
父级看不到这一点,因为它陷入了
semop
调用中。所以家长会永远等待。
所以,事情看起来像
semop
挂起/失败,但它不是。
如果parent进程收到
SIGFPE
,它将中止并且shell会报告这一点。但是,这个SIGFPE
是“沉默”的。它隐藏在等待的父母下面。 shell 只会看到父终止,在我们使用 SIGINT
停止它之后,它是 ctrl-c
。
为了找到这个错误,我制作了一个[大部分]重写的版本,其中包含很多的调试代码,我将在下面包含这些代码。
我通过运行
gdb
下的代码发现了这一点。
但是...
gdb
只是显示父级挂在semop
中。gdb
下,默认操作是 gdb
遵循 parent 流程,而不是 fork
之后的 child 流程。我必须告诉gdb
孩子而不是父母。 然后,
gdb
SIGFPE
并停止了执行。
错误,请使用-DBUG
进行编译:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#define SHM_SIZE 1024 // make it a 1K shared memory segment
#define MAX_FILES 10
#define MAX_LINES 10
/* Union semun */
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* array for GETALL, SETALL */
};
// Semaphore operations
struct sembuf wait_server = { 0, -1, SEM_UNDO };
struct sembuf signal_server = { 0, 1, SEM_UNDO };
struct sembuf wait_client = { 1, -1, SEM_UNDO };
struct sembuf signal_client = { 1, 1, SEM_UNDO };
// Shared data structure between threads
struct SharedData {
char shared_memory[SHM_SIZE];
int start_line;
int end_line;
int file_index;
int max_requests;
int client_request; // Store the client's request number
};
void
free_resources(int shm_id, int sem_id)
{
/* Delete the shared memory segment */
shmctl(shm_id, IPC_RMID, NULL);
/* Delete the semaphores */
semctl(sem_id, 0, IPC_RMID, 0);
semctl(sem_id, 1, IPC_RMID, 0);
}
/* Semaphore P - down operation, using semop */
int
sem_P(int sem_id, int sem_num)
{
struct sembuf sem_d;
sem_d.sem_num = sem_num;
sem_d.sem_op = -1;
sem_d.sem_flg = 0;
if (semop(sem_id, &sem_d, 1) == -1) {
perror("# Semaphore down (P) operation ");
return -1;
}
return 0;
}
/* Semaphore V - up operation, using semop */
int
sem_V(int sem_id, int sem_num)
{
struct sembuf sem_d;
sem_d.sem_num = sem_num;
sem_d.sem_op = 1;
sem_d.sem_flg = 0;
if (semop(sem_id, &sem_d, 1) == -1) {
perror("# Semaphore up (V) operation ");
return -1;
}
return 0;
}
/* Semaphore Init - set a semaphore's value to val */
int
sem_Init(int sem_id, int sem_num, int val)
{
union semun arg;
arg.val = val;
if (semctl(sem_id, sem_num, SETVAL, arg) == -1) {
perror("# Semaphore setting value ");
return -1;
}
return 0;
}
int
main(int argc, char *argv[])
{
// Passing arguments to variables
int N = atoi(argv[1]); // Number of clients
int K = atoi(argv[2]); // Total number of files
int L = atoi(argv[3]); // Number of requests per client
int shm_id;
int sem_id;
struct SharedData *data;
int pid;
printf("N=%d K=%d L=%d\n",N,K,L);
/* Create a new shared memory segment */
shm_id = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0660);
if (shm_id == -1) {
perror("Shared memory creation");
exit(EXIT_FAILURE);
}
/* Create a new semaphore id */
sem_id = semget(IPC_PRIVATE, 2, IPC_CREAT | 0660);
if (sem_id == -1) {
perror("Semaphore creation ");
shmctl(shm_id, IPC_RMID, (struct shmid_ds *) NULL);
exit(EXIT_FAILURE);
}
/* Set the value of the semaphores to 0 */
if (sem_Init(sem_id, 0, 0) == -1 || sem_Init(sem_id, 1, 0) == -1) {
free_resources(shm_id, sem_id);
exit(EXIT_FAILURE);
}
/* Attach the shared memory segment */
data = (struct SharedData *) shmat(shm_id, NULL, 0);
if (data == NULL) {
perror("Shared memory attach ");
free_resources(shm_id, sem_id);
exit(EXIT_FAILURE);
}
data->max_requests = L;
//int sleeptime;
// Register the signal handler for client finished
for (int i = 0; i < N; i++) {
/* New process */
//sleeptime = random() % 10;
if ((pid = fork()) == -1) {
perror("fork");
free_resources(shm_id, sem_id);
exit(EXIT_FAILURE);
}
if (pid == 0) {
printf("# I am the child process with process id: %d\n", getpid());
int j = 0;
while (j < data->max_requests) {
/* Child process */
// sem_V(sem_id, 1); // Signal server to process the request
// sem_P(sem_id, 0); // Wait for server to finish
data->file_index = rand() % MAX_FILES + 1;
data->start_line = rand() % MAX_LINES + 1;
// NOTE/BUG: this can produce an integer divide by zero which produces SIGFPE
#if BUG
data->end_line = rand() % (MAX_LINES - data->start_line) + data->start_line;
#else
data->end_line = rand();
// NOTE/FIX: this just prevents the SIGFPE but may not be exactly the same
int div = (MAX_LINES - data->start_line) + data->start_line;
if (div != 0)
data->end_line /= div;
#endif
printf("(%d): Client %d request %d\n", getpid(), i, j);
data->client_request = j + 1; // Set the client's request number
sem_V(sem_id, 1); // Signal server to process the request
// Wait for the server to process the request
sem_P(sem_id, 0); // Wait for server to finish
printf("(%d): Server processed request %d\n", getpid(), j);
j++;
printf("j is %d \n ", j);
}
/* Child process */
exit(EXIT_SUCCESS);
}
else {
/* Server process */
int j = 0;
while (j < data->max_requests) {
// sleep(5);
/* Wait for child process */
sem_V(sem_id, 0); // Signal client to continue
sem_P(sem_id, 1); // Wait for client to request
printf("# I am the server process with process id: %d\n", getpid());
// Process client requests here
printf("(%d): processing client requests\n", getpid());
// Example: Send a response to clients through shared memory
strcpy(data->shared_memory, "Response from server");
j++;
}
wait(NULL);
}
}
// Clear resources
free_resources(shm_id, sem_id);
return 0;
}
这是我的调试版本。它有很多调试代码,包括semop
的定时版本。如果发生超时,父进程将立即执行
wait
来收割子进程并取回 status
(显示 SIGFPE
)。#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <sys/file.h>
#define SHM_SIZE 1024 // make it a 1K shared memory segment
#define MAX_FILES 10
#define MAX_LINES 10
pid_t pid_dog;
pid_t pid_self;
pid_t pid_par;
pid_t pid_cld;
int opt_d; // 1=use watchdog
int opt_f; // 1=use flock on log
int opt_u; // 1=unified/single log
int opt_T; // 1=timeout (ms)
int shm_id = -1;
int sem_par = -1;
int sem_cld = -1;
// Union semun
union semun {
int val; // value for SETVAL
struct semid_ds *buf; // buffer for IPC_STAT, IPC_SET
unsigned short *array; // array for GETALL, SETALL
};
// Shared data structure between threads
struct SharedData {
char shared_memory[SHM_SIZE];
int client_request;
int start_line;
int end_line;
int file_index;
int max_requests;
};
#define dbgprtattr(_lvl) \
__attribute__((__format__(__printf__,_lvl,_lvl + 1)))
FILE *xflog;
double tsczero;
unsigned long long seqno; // sequence number
void
free_resources(int code)
{
// Delete the shared memory segment
if (pid_self == pid_par) {
if (shm_id >= 0)
shmctl(shm_id, IPC_RMID, NULL);
// Delete the semaphore
if (sem_par >= 0)
semctl(sem_par, 0, IPC_RMID, 0);
if (sem_cld >= 0)
semctl(sem_cld, 0, IPC_RMID, 0);
}
exit(code);
}
int
semnow(int sem_id)
{
int val = semctl(sem_id, 0, GETVAL);
return val;
}
const char *
semprt(int sem_id)
{
const char *tag;
if (sem_id == sem_par)
tag = "sem_par";
else
tag = "sem_cld";
#if 1
static char buf[100];
sprintf(buf,"%s/%d",tag,semnow(sem_id));
tag = buf;
#endif
return tag;
}
double
tscgetf(void)
{
struct timespec ts;
double sec;
clock_gettime(CLOCK_MONOTONIC,&ts);
sec = ts.tv_nsec;
sec /= 1e9;
sec += ts.tv_sec;
sec -= tsczero;
return sec;
}
const char *
pidshow(pid_t pid)
{
const char *tag;
do {
if ((pid == pid_dog) && opt_d) {
tag = "DOG";
break;
}
if (pid == pid_par) {
tag = "PAR";
break;
}
tag = "CLD";
} while (0);
return tag;
}
void dbgprtattr(1)
dbgprt(const char *fmt,...)
{
int sverr = errno;
char buf[1000];
va_list ap;
FILE *xfcur;
char *bp = buf;
const char *tag = pidshow(pid_self);
bp += sprintf(bp,"[%llu/%.9f/%s",seqno,tscgetf(),tag);
++seqno;
do {
if (tag[0] != 'P')
break;
if (pid_cld <= 0) {
bp += sprintf(bp,"/NCO");
break;
}
// FIXME/CAE -- this does _not_ detect a zombie (unreaped) child
int err = kill(pid_cld,0);
if (err >= 0) {
bp += sprintf(bp,"/AOK");
break;
}
bp += sprintf(bp,"/WTF");
} while (0);
bp += sprintf(bp,"] ");
va_start(ap,fmt);
bp += vsprintf(bp,fmt,ap);
va_end(ap);
xfcur = xflog;
if (xfcur == NULL)
xfcur = stdout;
if (opt_f)
flock(fileno(xfcur),LOCK_EX);
fputs(buf,xfcur);
fflush(xfcur);
if (opt_f)
flock(fileno(xfcur),LOCK_UN);
errno = sverr;
}
void
reap_show(const char *who,pid_t pid,int status)
{
char *bp;
char msg[100];
do {
bp = msg;
*bp = 0;
if (WIFEXITED(status)) {
bp += sprintf(bp," WIFEXITED code=%d",WEXITSTATUS(status));
break;
}
if (WIFSIGNALED(status)) {
bp += sprintf(bp," WIFSIGNALED signo=%d",WTERMSIG(status));
break;
}
} while (0);
dbgprt("%s: reaped pid=%s status=%8.8X --%s\n",
who,pidshow(pid),status,msg);
}
void
reap_child(int err)
{
int status;
pid_t pid;
dbgprt("reap_child: ENTER err=%d pid_cld=%d\n",err,pid_cld);
while (1) {
pid = wait(&status);
if (pid <= 0)
break;
reap_show("reap_child",pid,status);
}
dbgprt("reap_child: EXIT\n");
}
void
dbgerr(const char *who,int code)
{
dbgprt("dbgerr: %s (from %s)\n",strerror(errno),who);
if (code == 0)
code = 7;
if (code)
free_resources(code);
}
void
openlog(pid_t pid)
{
char tail[100];
char file[300];
do {
if (opt_u) {
sprintf(tail,"com.log");
break;
}
sprintf(tail,"%s.log",pidshow(pid));
} while (0);
for (char *cp = tail; *cp != 0; ++cp)
*cp = tolower((unsigned char) *cp);
const char *dir = getenv("GENDIR");
if (dir == NULL)
dir = ".";
sprintf(file,"%s/%s",dir,tail);
xflog = fopen(file,"a");
setlinebuf(xflog);
seqno = 0;
}
int
semxop(int semid, struct sembuf *sops, size_t nsops)
{
struct timespec ts;
long long tmout = opt_T;
tmout *= 1000000;
ts.tv_nsec = tmout % 1000000000;
ts.tv_sec = tmout / 1000000000;
int err = semtimedop(semid,sops,nsops,opt_T ? &ts : NULL);
if ((err < 0) && (errno == EAGAIN)) {
dbgprt("semxop: TIMEOUT val=%s\n",semprt(semid));
reap_child(1);
free_resources(1);
}
return err;
}
// Semaphore P - down operation, using semop
int
semunlock(int sem_id)
{
struct sembuf sem_d;
dbgprt("semunlock: ENTER sem_id=%s\n",semprt(sem_id));
sem_d.sem_num = 0;
sem_d.sem_op = -1;
sem_d.sem_flg = 0;
if (semxop(sem_id, &sem_d, 1) == -1) {
dbgerr("semunlock",0);
return -1;
}
dbgprt("semunlock: EXIT sem_id=%s\n",semprt(sem_id));
return 0;
}
// Semaphore V - up operation, using semop
int
semlock(int sem_id)
{
struct sembuf sem_d;
dbgprt("semlock: ENTER sem_id=%s\n",semprt(sem_id));
sem_d.sem_num = 0;
sem_d.sem_op = 1;
sem_d.sem_flg = 0;
if (semxop(sem_id, &sem_d, 1) == -1) {
dbgerr("semlock",0);
return -1;
}
dbgprt("semlock: EXIT sem_id=%s\n",semprt(sem_id));
return 0;
}
// Semaphore Wait - up operation, using semop
int
semwait(int sem_id)
{
struct sembuf sem_d;
dbgprt("semwait: ENTER sem_id=%s\n",semprt(sem_id));
sem_d.sem_num = 0;
sem_d.sem_op = 0;
sem_d.sem_flg = 0;
if (semxop(sem_id, &sem_d, 1) == -1) {
dbgerr("semwait",0);
return -1;
}
dbgprt("semwait: EXIT sem_id=%s\n",semprt(sem_id));
return 0;
}
// Semaphore Init - set a semaphore's value to val
int
seminit(int sem_id, int sval)
{
union semun arg;
arg.val = sval;
if (semctl(sem_id, 0, SETVAL, arg) == -1) {
dbgerr("seminit",0);
return -1;
}
return 0;
}
// Semaphore Create -- create a semaphore and set its value
int
semnew(int val)
{
int sem_id;
// Create a new semaphore id
sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0660);
if (sem_id == -1) {
dbgerr("semnew",1);
}
if (seminit(sem_id,val) < 0)
free_resources(1);
return sem_id;
}
void
data_show(struct SharedData *data,int j)
{
dbgprt("j=%d client_request=%d file_index=%d start_line=%d end_line=%d max_requests=%d\n",
j,data->client_request,data->file_index,data->start_line,data->end_line,
data->max_requests);
}
void
watchdog(pid_t pid)
{
int status;
if (! opt_u)
openlog(pid_dog);
pid_par = pid;
while (1) {
pid = wait(&status);
if (pid < 0)
break;
reap_show("watchdog",pid,status);
}
fclose(xflog);
exit(0);
}
void
docld(struct SharedData *data)
{
int j = 0;
while (j < data->max_requests) {
dbgprt("# I am the child process -- j=%d\n",j);
// Child process
if (j > 0)
semwait(sem_cld);
dbgprt("docld: DATABEG\n");
data->file_index = rand() % MAX_FILES + 1;
data->start_line = rand() % MAX_LINES + 1;
#if BUG
data->end_line = rand() %
(MAX_FILES - data->start_line) + data->start_line;
#else
int div = (MAX_FILES - data->start_line) + data->start_line;
if (div == 0) {
dbgprt("docld: fatal div=%d\n",div);
free_resources(97);
}
data->end_line = rand() % div;
#endif
data->client_request = j;
dbgprt("docld: DATAEND\n");
semlock(sem_cld);
semunlock(sem_par);
data_show(data,j);
j++;
}
// Child process
dbgprt("child done\n");
fclose(xflog);
exit(EXIT_SUCCESS);
}
void
dopar(struct SharedData *data)
{
int j = 0;
while (j < data->max_requests) {
dbgprt("# I am the parent process -- j=%d\n",j);
semwait(sem_par);
#if 0
char mystring[74];
#else
char mystring[200];
#endif
sprintf(mystring, "Client requested lines %d to %d from file %d\n",
data->start_line, data->end_line, data->file_index);
data_show(data,j);
semlock(sem_par);
semunlock(sem_cld);
j++;
}
reap_child(0);
dbgprt("parent done\n");
fclose(xflog);
}
int
main(int argc, char **argv)
{
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
char *cp = *argv;
if (*cp != '-')
break;
cp += 2;
switch (cp[-1]) {
case 'd':
opt_d = 1;
break;
case 'f':
opt_f = 1;
break;
case 'T':
opt_T = (*cp != 0) ? atoi(cp) : 1000;
break;
case 'u':
opt_u = 1;
break;
default:
printf("unknown option -- '%s'\n",cp - 2);
exit(1);
break;
}
}
// Passing arguments to variables
if (argc != 3) {
printf("usage: num_of_clients num_of_files num_of_requests\n");
exit(1);
}
int N = atoi(argv[0]); // Number of clients
int K = atoi(argv[1]); // Total number of files
int L = atoi(argv[2]); // Number of requests per client
struct SharedData *data;
int pid;
tsczero = tscgetf();
pid_par = getpid();
pid_self = pid_par;
pid_dog = pid_par;
unlink("par.log");
unlink("cld.log");
unlink("com.log");
unlink("dog.log");
printf("opt_T=%d opt_d=%d opt_u=%d\n",opt_T,opt_d,opt_u);
printf("N=%d K=%d L=%d\n",N,K,L);
// Create a new shared memory segment
#if 0
shm_id = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0660);
#else
shm_id = shmget(IPC_PRIVATE, sizeof(*data), IPC_CREAT | 0660);
#endif
if (shm_id == -1) {
dbgerr("shmget",1);
}
// Create a new semaphore id
sem_par = semnew(1);
sem_cld = semnew(1);
// Attach the shared memory segment
data = shmat(shm_id, NULL, 0);
if (data == NULL) {
dbgerr("shmat",1);
}
// open single/unified log
if (opt_u)
openlog(pid_self);
else
opt_f = 0;
data->max_requests = L;
if (opt_d) {
pid = fork();
pid_self = getpid();
if (pid != 0)
watchdog(pid);
else
pid_par = pid_self;
}
for (int i = 0; i < N; i++) {
seminit(sem_par,1);
seminit(sem_cld,0);
// New process
pid_cld = fork();
if (pid_cld < 0) {
dbgerr("fork",1);
}
pid_self = getpid();
do {
if (opt_u)
break;
openlog(pid_self);
} while (0);
dbgprt("i=%d N=%d K=%d L=%d\n",i,N,K,L);
// Child process
if (pid_cld == 0)
docld(data);
// Parent process
else
dopar(data);
}
// Clear recourses
free_resources(0);
return 0;
}
测试我使用的程序:./program -T -d -u 10 5 50
您的程序没有
有这些选项,所以您可以使用:
./program 10 5 50
[0/0.001266244/CLD] i=0 N=10 K=5 L=50
[1/0.001298536/CLD] # I am the child process -- j=0
[2/0.001307860/CLD] docld: DATABEG
[3/0.001315689/CLD] docld: DATAEND
[4/0.001329338/CLD] semlock: ENTER sem_id=sem_cld/0
[5/0.001342283/CLD] semlock: EXIT sem_id=sem_cld/1
[6/0.001350356/CLD] semunlock: ENTER sem_id=sem_par/1
[7/0.001364993/CLD] semunlock: EXIT sem_id=sem_par/0
[8/0.001371790/CLD] j=0 client_request=0 file_index=4 start_line=7 end_line=7 max_requests=50
[9/0.001377922/CLD] # I am the child process -- j=1
[10/0.001384828/CLD] semwait: ENTER sem_id=sem_cld/1
[11/0.002007042/CLD] semwait: EXIT sem_id=sem_cld/0
[12/0.002028876/CLD] docld: DATABEG
[13/0.002033988/CLD] docld: DATAEND
[14/0.002039242/CLD] semlock: ENTER sem_id=sem_cld/0
[15/0.002047293/CLD] semlock: EXIT sem_id=sem_cld/1
[16/0.002055879/CLD] semunlock: ENTER sem_id=sem_par/1
[17/0.002069514/CLD] semunlock: EXIT sem_id=sem_par/0
[18/0.002075485/CLD] j=1 client_request=1 file_index=6 start_line=4 end_line=5 max_requests=50
[19/0.002083478/CLD] # I am the child process -- j=2
[20/0.002095297/CLD] semwait: ENTER sem_id=sem_cld/1
[21/0.002134363/CLD] semwait: EXIT sem_id=sem_cld/0
[22/0.002151245/CLD] docld: DATABEG
[23/0.002164216/CLD] docld: DATAEND
[24/0.002176661/CLD] semlock: ENTER sem_id=sem_cld/0
[25/0.002191834/CLD] semlock: EXIT sem_id=sem_cld/1
[26/0.002206599/CLD] semunlock: ENTER sem_id=sem_par/1
[27/0.002226650/CLD] semunlock: EXIT sem_id=sem_par/0
[28/0.002239249/CLD] j=2 client_request=2 file_index=7 start_line=3 end_line=4 max_requests=50
[29/0.002249359/CLD] # I am the child process -- j=3
[30/0.002260278/CLD] semwait: ENTER sem_id=sem_cld/1
[31/0.002302774/CLD] semwait: EXIT sem_id=sem_cld/0
[32/0.002315361/CLD] docld: DATABEG
[33/0.002322812/CLD] docld: DATAEND
[34/0.002331089/CLD] semlock: ENTER sem_id=sem_cld/0
[35/0.002340748/CLD] semlock: EXIT sem_id=sem_cld/1
[36/0.002349374/CLD] semunlock: ENTER sem_id=sem_par/1
[37/0.002361950/CLD] semunlock: EXIT sem_id=sem_par/0
[38/0.002369377/CLD] j=3 client_request=3 file_index=2 start_line=3 end_line=8 max_requests=50
[39/0.002376160/CLD] # I am the child process -- j=4
[40/0.002383759/CLD] semwait: ENTER sem_id=sem_cld/1
[41/0.002476519/CLD] semwait: EXIT sem_id=sem_cld/0
[42/0.002486868/CLD] docld: DATABEG
请注意,我们没有
看到关闭docld: DATAEND
,因此子进程在它们之间中止(即)
rand
调用是问题所在。
这是带有附加 wait
调用的父日志:
[0/0.001215808/PAR/AOK] i=0 N=10 K=5 L=50
[1/0.001263264/PAR/AOK] # I am the parent process -- j=0
[2/0.001272759/PAR/AOK] semwait: ENTER sem_id=sem_par/1
[3/0.001385589/PAR/AOK] semwait: EXIT sem_id=sem_par/0
[4/0.001403069/PAR/AOK] j=0 client_request=0 file_index=4 start_line=7 end_line=7 max_requests=50
[5/0.001415180/PAR/AOK] semlock: ENTER sem_id=sem_par/0
[6/0.001426980/PAR/AOK] semlock: EXIT sem_id=sem_par/1
[7/0.001435772/PAR/AOK] semunlock: ENTER sem_id=sem_cld/1
[8/0.001452325/PAR/AOK] semunlock: EXIT sem_id=sem_cld/0
[9/0.001461888/PAR/AOK] # I am the parent process -- j=1
[10/0.001472132/PAR/AOK] semwait: ENTER sem_id=sem_par/1
[11/0.002075115/PAR/AOK] semwait: EXIT sem_id=sem_par/0
[12/0.002091506/PAR/AOK] j=1 client_request=1 file_index=6 start_line=4 end_line=5 max_requests=50
[13/0.002098502/PAR/AOK] semlock: ENTER sem_id=sem_par/0
[14/0.002106132/PAR/AOK] semlock: EXIT sem_id=sem_par/1
[15/0.002112009/PAR/AOK] semunlock: ENTER sem_id=sem_cld/1
[16/0.002122503/PAR/AOK] semunlock: EXIT sem_id=sem_cld/0
[17/0.002127650/PAR/AOK] # I am the parent process -- j=2
[18/0.002133836/PAR/AOK] semwait: ENTER sem_id=sem_par/1
[19/0.002234273/PAR/AOK] semwait: EXIT sem_id=sem_par/0
[20/0.002248679/PAR/AOK] j=2 client_request=2 file_index=7 start_line=3 end_line=4 max_requests=50
[21/0.002261339/PAR/AOK] semlock: ENTER sem_id=sem_par/0
[22/0.002274647/PAR/AOK] semlock: EXIT sem_id=sem_par/1
[23/0.002284569/PAR/AOK] semunlock: ENTER sem_id=sem_cld/1
[24/0.002294957/PAR/AOK] semunlock: EXIT sem_id=sem_cld/0
[25/0.002300563/PAR/AOK] # I am the parent process -- j=3
[26/0.002306849/PAR/AOK] semwait: ENTER sem_id=sem_par/1
[27/0.002410154/PAR/AOK] semwait: EXIT sem_id=sem_par/0
[28/0.002423106/PAR/AOK] j=3 client_request=3 file_index=2 start_line=3 end_line=8 max_requests=50
[29/0.002434989/PAR/AOK] semlock: ENTER sem_id=sem_par/0
[30/0.002447388/PAR/AOK] semlock: EXIT sem_id=sem_par/1
[31/0.002457822/PAR/AOK] semunlock: ENTER sem_id=sem_cld/1
[32/0.002468612/PAR/AOK] semunlock: EXIT sem_id=sem_cld/0
[33/0.002474043/PAR/AOK] # I am the parent process -- j=4
[34/0.002480116/PAR/AOK] semwait: ENTER sem_id=sem_par/1
[35/1.041000029/PAR/AOK] semxop: TIMEOUT val=sem_par/1
[36/1.041029481/PAR/AOK] reap_child: ENTER err=1 pid_cld=1903742
[37/3.102558362/PAR/WTF] reap_child: reaped pid=CLD status=00000088 -- WIFSIGNALED signo=8
[38/3.102589796/PAR/WTF] reap_child: EXIT
注意第 37 行:
status
是
00000088
,这是以信号 8 终止(在我的系统上是 SIGFPE
)。