关于信号量同步,最后一次写入当前时间进入文件产生阻塞的问题

关于信号量同步,最后一次写入当前时间进入文件产生阻塞的问题

问题描述:

在练习中,将当前时间写入文件中,但是当写入的记录数超过25时,最后一条信息会不完整,且程序出现阻塞,目前测试是因为卡在了第二次占用SEM_P后,发生阻塞,导致最后一条时间信息结尾不完整,程序也无法正常退出。按照理论在子进程释放SEM_P中的资源后,就可以继续进行,但是不知道为什么就是出现了阻塞。

			sem_p(semid, SEM_P);
			//sprintf(buf, ">\n");
			fwrite(">\n", 1, 2, fp);
			fflush(fp);
			sem_v(semid, SEM_P);


程序的相关代码:

sem.h

#ifndef __SEM__H__
#define __SEM__H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

// 创建信号类列表
extern int sem_creat(int nums, unsigned short value[]);

// 占用资源
extern int sem_p(int semid, int num);

// 释放资源
extern int sem_v(int semid, int num);

// 删除信号量列表
extern int sem_del(int semid);

// 获取信号量的资源个数
extern int get_val(int semid, int num);
#endif

sem.c

#include "sem.h"

#define SEM_PATHNAME "."
#define SEM_PRO_ID 99

union semun
{
	unsigned short *arrry;
};

/*
 	创建信号量列表
	@param nums : 信号量列表中的信号个数
	@param value : 各个信号量的资源值
	@return error : -1, success : semid
 */
int sem_creat(int nums, unsigned short value[])
{
	key_t key;
	int semid;

	key = ftok(SEM_PATHNAME, SEM_PRO_ID);
	if( -1 == key )
		return -1;

	semid = semget(key, nums, IPC_CREAT | 0644);
	if( -1 == semid )
		return -1;

	union semun s;
	s.arrry = value;
	semctl(semid, 0, SETALL, s);

	return semid;
}

/*
	 占用资源
	 @param semid : 信号量列表id 
	 @param num : 列表中具体信号量下标
 */
int sem_p(int semid, int num)
{
	struct sembuf s;
	s.sem_num = num;
	s.sem_op = -1;
	s.sem_flg = SEM_UNDO;

	return semop(semid, &s, 1);
}

/*
 	释放资源
	@param semid : 型号量列表id
	@param num : 型号量列表中的具体信号
*/
int sem_v(int semid, int num)
{
	struct sembuf s;
	s.sem_num = num;
	s.sem_op = 1;
	s.sem_flg = SEM_UNDO;

	return semop(semid, &s, 1);
}

// 删除信号量列表
int sem_del(int semid)
{
	return semctl(semid, 0, IPC_RMID, NULL);
}

/*
 	获取信号量的资源个数
	@param semid : 信号量列表id
	@param num : 信号量列表中的具体信号量下标
*/
int get_val(int semid, int num)
{
	union semun	{
		int val;
	};
	union semun s;
	return semctl(semid, num, GETVAL, s);
}

main.c

#include "sem.h"

#include <unistd.h>
#include <sys/wait.h>
#include <time.h>

#define SEM_P 0
#define SEM_C 1

#define MAX 60 * 1

int main(void)
{
	int cpid;
	int semid;
	unsigned short value[] = {1, 0};
	FILE *fp;

	semid = sem_creat(2, value);
	if( -1 == semid )
	{
		perror("[ERROR] sem_creat()");
		return -1;
	}

	fp = fopen("./time.txt", "a");
	if( NULL == fp )
	{
		printf("fopen() error.\n");
		return -1;
	}
	
	cpid = fork();
	if( -1 == cpid )
	{
		perror("[ERROR] fork()");
		return -1;
	}else if( 0 == cpid ) // 子进程
	{
		int count = 0;
		while( (++count) <= MAX )
		{
			//sleep(1);
			time_t t;
			struct tm *info;
			time(&t);
			info = localtime(&t);

			sem_p(semid, SEM_C);
			char buf[64];
			sprintf(buf, "%d-%d-%d %d:%d:%d", info->tm_year+1900,
					info->tm_mon+1,
					info->tm_mday,
					info->tm_hour,
					info->tm_min,
					info->tm_sec);
			fwrite(buf, 1, strlen(buf), fp);
			fflush(fp);
			sem_v(semid, SEM_P);
		}
		fclose(fp);
	}else if( cpid > 0 ) // 父进程
	{
		int count = 0;
		while( (++count) <= MAX )
		{
			sem_p(semid, SEM_P);
			char buf[4];
			sprintf(buf, "%d,<", count);
			fwrite(buf, 1, strlen(buf), fp);
			fflush(fp);
			sem_v(semid, SEM_C);

			sem_p(semid, SEM_P);
			//sprintf(buf, ">\n");
			fwrite(">\n", 1, 2, fp);
			fflush(fp);
			sem_v(semid, SEM_P);
			sleep(1);
		}

		wait(NULL);
		sem_del(semid);
		fclose(fp);
	}
	return 0;
}


相关截图:

当写入60条的时候,程序不能正常退出

https://img1.sycdn.imooc.com//climg/64d5afa60986e98412650809.jpg

当写入20条的时候,程序可以正常退出

https://img1.sycdn.imooc.com//climg/64d5b51b096e24b210570604.jpg


正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
无__名 2023-08-11 14:07:26

你的测试代码经过测试60s 可正常退出,并正确写入了时间,麻烦联系一下无名老师(308828790),进一步沟通https://img1.sycdn.imooc.com//climg/64d5cfb109a9c98406060523.jpg


问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师