模拟临界资源访问

这篇文章介绍了一个使用C语言实现的共享内存和信号处理的并发控制示例。通过`shmget`和`semget`创建共享内存和信号量,实现在服务器端分配和管理块,客户端请求和释放资源。主要关注get和rel命令操作共享内存块的流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

#define MY_SHMKEY 10071800		// need to change
#define MY_SEMKEY 10071800		// need to change

#define MAX_BLOCK 1024
#define MAX_CMD 8

struct shmbuf {
    int top;
    int stack[MAX_BLOCK];
} *shmptr, local;
char cmdbuf[MAX_CMD];
int shmid, semid;
int semval;
struct sembuf semopbuf;

void sigend(int);
void relblock(void);
int  getblock(void);
void showhelp(void);
void showlist(void);
void getcmdline(void);

int main(void)
{
    if((shmid=shmget(MY_SHMKEY, sizeof(struct shmbuf), IPC_CREAT|IPC_EXCL|0666)) < 0)
    {			/* shared memory exists, act as client */
        semid=semget(MY_SEMKEY, 1, 0666);
        shmid=shmget(MY_SHMKEY, sizeof(struct shmbuf), 0666);
        shmptr=(struct shmbuf *)shmat(shmid, 0, 0);
        local.top=-1;
        showhelp();
        getcmdline();
        while(strcmp(cmdbuf,"end\n"))
	{
	    
	    
	    if(!strcmp(cmdbuf,"get\n"))
		getblock();
	    else if(!strcmp(cmdbuf,"rel\n"))
		relblock();
	    else if(!strcmp(cmdbuf,"list\n"))
		showlist();
	    else if(!strcmp(cmdbuf,"help\n"))
		showhelp();
	    getcmdline();
	    
        }
    }
    else		/* acts as server */
    {
        semid=semget(MY_SEMKEY, 1, IPC_CREAT|0666);
        
        semval=1; 
        semctl(semid, 0, SETVAL, semval); /* set S1=1 */ 
        int i;
        shmptr=(struct shmbuf *)shmat(shmid, 0, 0);
        signal(SIGINT, sigend);
        signal(SIGTERM, sigend);
        printf("NO OTHER OPERATION but press Ctrl+C or use kill to end.\n");
		shmptr->top=MAX_BLOCK-1;
		for(i=0; i<MAX_BLOCK; i++)
		    shmptr->stack[i]=MAX_BLOCK-i;
        sleep(1000000);	/* cause sleep forever. */ 
    }
}

void sigend(int sig)
{
    shmctl(shmid, IPC_RMID, 0);
    semctl(semid, IPC_RMID, 0);
    exit(0);
}

void relblock(void)
{
    semopbuf.sem_num=0; 
    semopbuf.sem_op=-1; 
    semopbuf.sem_flg=SEM_UNDO; 
    semop(semid, &semopbuf, 1); /* P(S1) */
    if(local.top<0)
    {
			printf("No block to release!");
			return;
    }
    shmptr->top++;
    shmptr->stack[shmptr->top]=local.stack[local.top--];
    semopbuf.sem_num=0; 
    semopbuf.sem_op=1; 
    semopbuf.sem_flg=SEM_UNDO; 
    semop(semid, &semopbuf, 1); /* V(S1) */
}

int  getblock(void)
{
    semopbuf.sem_num=0; 
    semopbuf.sem_op=-1; 
    semopbuf.sem_flg=SEM_UNDO; 
    semop(semid, &semopbuf, 1); /* P(S1) */
    if(shmptr->top<0)
    {
			printf("No free block to get!");
			return 0;
    }
    local.stack[++local.top]=shmptr->stack[shmptr->top];
    sleep(8);
    shmptr->top--;
    semopbuf.sem_num=0; 
    semopbuf.sem_op=1; 
    semopbuf.sem_flg=SEM_UNDO; 
    semop(semid, &semopbuf, 1); /* V(S1) */
    
}

void showhelp(void)
{
    printf("\available COMMAND:\n\n");
    printf("help\tlist this help\n");
    printf("list\tlist all gotten block number\n");
    printf("get\tget a new block\n");
    printf("rel\trelease the last gotten block\n");
    printf("end\texit this program\n");
}

void showlist(void)
{
    int i;
    printf("List all gotten block number:\n");
    for(i=0; i<=local.top; i++)
	printf("%d\t", local.stack[i]);
}

void getcmdline(void)
{
    printf("\n?> ");
    fgets(cmdbuf, MAX_CMD-1, stdin);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值