野火Linux第65/66/67讲:system-V消息队列\信号量\共享内存编程经历

一、消息队列

①学习各种不熟悉的函数

1. strncmp()

库文件:string.h

strncmp函数为字符串比较函数,字符串大小的比较是以ASCII 码表上的顺序来决定,此顺序亦为字符的值。其函数声明为

int strncmp ( const char * str1, const char * str2, size_t n );

功能是把 str1 和 str2 进行比较,最多比较前 n 个字节,若str1与str2的前n个字符相同,则返回0;若s1大于s2,则返回大于0的值;若s1 小于s2,则返回小于0的值。

2. strncpy()

库文件:string.h

char *strncpy(char *dest, const char *src, int n)

用于将指定长度的字符串复制到字符数组中,表示把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回被复制后的dest。

2. perror()

库文件:stdio.h

void perror ( const char * str );
perror(s) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。
库函数中有个errno变量,每个errno值对应着以字符串表示的错误类型。当你调用某些函数出错时,该函数已经重新设置了errno的值。perror函数只是将你输入的一些信息和errno所对应的错误一起输出。

3. exit()

头文件:stdlib.h(如果是”VC6.0“的话头文件为:windows.h)

stdlib.h: void exit(int status);//参 数status,程序退出的返回值

功 能: 关闭所有文件,终止正在执行的进程。

exit(0)表示正常退出,
exit(x)(x不为0)都表示异常退出,这个x是返回给操作系统(包括UNIX,Linux,和MS DOS)的,以供其他程序使用。
与_exit()的头文件不同:
_exit:#include<unistd.h>
_exit()函数:直接使进程停止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;
exit()函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序。
exit()函数与_exit()函数最大的区别就在于 exit()函数在调用 exit 系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件。
 
 

 ②调试错误

 在写完程序后,程序从一开始创建消息队列就开始抛锚。

 后来发现是自己代码中的用于创建函数队列的 msgget()没设置对,函数原型如下:

int msgget(key_t key,int msgflg) msgflg:IPC_CREAT:如果消息队列不存在,则创建

参数:

  • key:消息队列的键值

  • msgflg:

    • IPC_CREAT:如果消息队列不存在,则创建

    • mode:访问权限

返回值:

成功:该消息队列的ID

失败:-1

 

我错误的代码如下:

msgget(key,IPC_CREAT|0x666)

将0x666改为0666就可以了。(一种猜想是:虽然两个数字相同,但是16进制可能每一个数比8进制多占了一位)

 

二、信号量

调试过程中发现两个错误,

一个是官方笔记的参数的错误,应该改为SETVAL(没有前面的IPC_, 否则编译的时候会出现未定义错误)

 二是关于运算符优先级的问题,以常见的fork()函数为例,以下代码的红色部分存在错误:

1     pid_t pid;
2     // fork a new process
3     if(pid=fork() < 0) //应该改成 if((pid=fork())<0)
4     {
5         printf("fork failed.\n");
6         exit(-1);
7     }

“<”的优先级要大于“=”的优先级,因此如果父进程执行的话,因为fork()的值大于0 ----》“<"的逻辑判断为假-----》pid 被赋值为0,发生了错误。

 

 三、共享内存

①别忘记包含头文件哦

 包含库函数的规律:一般ipc 包括两个通用的头文件,和一个信号量特用的头文件

 1 //通用需要的头文件
 2 #include <sys/types.h>
 3 #include <sys/ipc.h>
 4 
 5 //信号量特有
 6 #include <sys/msg.h>
 7 
 8 //信号量特有
 9 #include <sys/sem.h>
10 
11 //共享内存特有
12 #include <sys/shm.h>

②、信号量映射内存函数shmat()返回类型说明

函数说明如下

int shmat(int shmid,const void *shmaddr,int shmflg)
/*
- shmid:共享内存ID
- shmaddr:映射地址,NULL为自动分配
- shmflg:
  - SHM_RDONLY:只读方式映射
  - 0:可读可写
  返回值:
        成功:共享内存首地址
        失败:-1
*/
由操作系统申请一段内存,性质为可读可写,返回其共享内存的首地址

该函数原型返回值的类型为int,但是其性质为指针。因此在写程序的时候,常常要做强制类型转化,防止警告。

void *shm = NULL;//定义一个共享内存的指针
//将共享内存连接到当前进程的地址空间,地址由Linux操作系统指定(NULL参数)
shm =(void *)shmat(shmid, NULL, 0);

 

 

posted @ 2023-05-08 22:34  FBshark  阅读(34)  评论(0编辑  收藏  举报