栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux&C语言简单实现线程间通信-信号量(灯)集-IO进程

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux&C语言简单实现线程间通信-信号量(灯)集-IO进程

1. 基于C语言实现,IO进程-进程间通信-信号量练习 2. 代码实现 信号量的API(ftok|semget|semop|semctl)参考1 | 参考2 01sem.h
#ifndef __SEM_H__
#define __SEM_H__
#include 

#include 

#include 

#include 


#include 

// 1、获取key值-创建信号量   ->2、初始化
int sem_init(void);

//3、信号灯的操作(PV)semop
//3、1 P操作代表申请资源
int P(int semid, int semnum);
//3、2 V操作代表释放资源
int V(int semid, int semnum);

//4、删除信号灯semctl
int sem_del(int semid);

#endif
02sem信号灯.c
#include 

#include 

#include 
#include 

#include 
//2、1定义联合体
union semun
{
    int val;               //!!!!!!!
    struct semid_ds *buf;  
    unsigned short *array; 
    struct seminfo *__buf; 
};
//2、初始化信号量semctl
int init_semnum_value(int semid, int semnum, int value)
{
    union semun sem;//定义联合体   要写定义
    sem.val = value;//设置信号灯的值 !!!!!!!!!!!!!!!
    
                    //信号灯的编号,SETVAL[设置信号灯的值] 
    if (semctl(semid, semnum, SETVAL, sem) < 0)
        printf("semctl init value error");
    return 0;
}
// 1、获取key值-创建信号量   ->2、初始化
int sem_init(void)
{
    // 1.获取key值
    key_t key;
                    //改你有的目录
    if ((key = ftok("/home/linux", 'w')) == -1)
        printf("ftok error");

    // 2.创建信号量semget
    //如果信号量不存在就创建信号量,创建号信号量后执行else语句对
    //信号灯的初值进行初始化
    //如果信号量已存在,IPC_EXCL这个就会让semget报EEXIST,如果
    //信号灯已存在,直接获取信号灯semid,否则打印错误。如果信号
    //量已存在就不再对信号量中的信号灯的初值做初始化了
    int semid;                      //创建|存在
    if ((semid = semget(key, 2, IPC_CREAT | IPC_EXCL | 0664)) == -1)
    {
        if (errno == EEXIST)//存在-返回错误码EEXIST
        {
            semid = semget(key, 2, IPC_CREAT | 0664);//semget成功返回ID
        }
        else
        {
            printf("create sem error");
        }
    }
    else
    {
        // 3.初始化信号量semctl
        //初始化信号灯集中的两个信号灯的初值
        // 0号灯的初值为0
        // 1号灯的初值为1
        init_semnum_value(semid, 0, 0);
        init_semnum_value(semid, 1, 1);
    }

    return semid;
}
//3、信号灯的操作(PV)semop
//3、1 P操作代表申请资源
int P(int semid, int semnum)
{
    struct sembuf buf;//操作方式结构体   不用写结构体定义
    buf.sem_num = semnum;//信号灯的编号
    buf.sem_op = -1; //申请资源
    buf.sem_flg = 0; //阻塞方式申请

                    //操作方式结构体首地址,1操作信号灯的个数 
    if (semop(semid, &buf, 1) < 0)
        printf("P error");

    return 0; //成功返回0
}

//3、2 V操作代表释放资源
int V(int semid, int semnum)
{
    struct sembuf buf;//操作方式结构体    不用写结构体定义
    buf.sem_num = semnum;//信号灯的编号
    buf.sem_op = 1;  //释放资源
    buf.sem_flg = 0; //阻塞方式申请

                    //操作方式结构体首地址,1操作信号灯的个数 
    if (semop(semid, &buf, 1) < 0)
        printf("V error");

    return 0; //成功返回0
}
//4、删除信号灯semctl
int sem_del(int semid)
{
    // 1.删除信号灯集合--IPC_RMID[删除信号灯集]
    if (semctl(semid, 0, IPC_RMID, NULL) == -1)
        printf("delete sem error");
}
03write.c
#include "./01sem.h"

//申请共享内存的大小
#define shmSIZE 4096

int main(int argc, char const *argv[])
{
    // 1、创建信号量---信号灯集
    int semid; //信号灯集的ID
    if ((semid = sem_init()) == -1)
        printf("sem_init error");
    printf("semid = %dn", semid);

    // 1.获取key----共享内存
    key_t key;
                    //改你有的目录
    if ((key = ftok("/home/linux", 't')) == -1)
        printf("ftok eroorn");

    // 2.创建共享内存----共享内存
    int shmid;
    if ((shmid = shmget(key, shmSIZE, IPC_CREAT | 0664)) == -1)
        printf("shmget eroorn");
    printf("shmid = %dn", shmid);
    // 3.映射内存----共享内存
    //映射后的地址
    // char *addr=NULL;
    char *addr;
    if ((addr = shmat(shmid, NULL, 0)) == (void *)-1)
        printf("shmat eroorn");

    // 4.写入信息----共享内存
    while (1)
    {
        //2、信号灯的操作
        //2、1 P操作代表申请资源
        P(semid,1);
        printf("老王>  ");
        //从终端获取信息
        fgets(addr, shmSIZE, stdin);
        //处理输入最后一个换行符
        addr[strlen(addr) - 1] = '';
       
        //2、2 V操作代表释放资源
        V(semid,0);//----->read要申请0号灯

        if (strcmp(addr,"quit")==0)
            break;

        

        // 2、3 P操作代表申请资源
        P(semid, 0);
        printf("n");
        system("date") ;
        printf("小姐姐>   %sn", addr);
        printf("n");
        // 2、4 V操作代表释放资源
        V(semid, 1);
        if (strcmp(addr, "quit") == 0)
            break;
    }

    //删除共享内存
    shmctl(shmid, IPC_RMID, NULL);
    //3、删除信号灯集
    sem_del(semid);
    return 0;
}

04read.c
#include "./01sem.h"

//申请共享内存的大小
#define shmSIZE 4096

int main(int argc, char const *argv[])
{
    // 1、创建信号量---信号灯集
    int semid; //信号灯集的ID
    if ((semid = sem_init()) == -1)
        printf("sem_init error");
    printf("semid = %dn", semid);

    // 1.获取key----共享内存
    key_t key;
                    //改你有的目录
    if ((key = ftok("/home/linux", 't')) == -1)
        printf("ftok eroorn");

    // 2.创建共享内存----共享内存
    int shmid;
    if ((shmid = shmget(key, shmSIZE, IPC_CREAT | 0664)) == -1)
        printf("shmget eroorn");
    printf("shmid = %dn", shmid);
    // 3.映射内存----共享内存
    //映射后的地址
    // char *addr=NULL;
    char *addr;
    if ((addr = shmat(shmid, NULL, 0)) == (void *)-1)
        printf("shmat eroorn");
        
    // 4.读取信息----共享内存
    //从终端获取信息
    while (1)
    {
        

        // 2、信号灯的操作
        // 2、1 P操作代表申请资源
        P(semid, 0);
        printf("n");
        system("date") ;
        printf("老王>   %sn", addr);
        printf("n");
        // 2、2 V操作代表释放资源
        V(semid, 1);
        if (strcmp(addr, "quit") == 0)
            break;

        //2、3 P操作代表申请资源
        P(semid, 1);
        printf("小姐姐>  ");
        //从终端获取信息
        fgets(addr, shmSIZE, stdin);
        //处理输入最后一个换行符
        addr[strlen(addr) - 1] = '';
        //2、4 V操作代表释放资源
        V(semid,0);
        if (strcmp(addr,"quit")==0)
            break;
    }
    return 0;
}
执行命令

1.gcc 03write.c 02sem信号灯.c -o write
2…/write
3.gcc 02sem信号灯.c 04read.c -o read
4…/read

执行结果 bug解决

执行如下命令->删除原有的 semid

quit退出

6. 非原创
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/870019.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号