- 浏览: 168149 次
- 性别:
- 来自: 成都
-
文章分类
最新评论
-
abc08010051:
简单明了,非常不错
java.lang.Thread.State类详解 -
tenderlitch:
jdk api文档里面的描述...
set闲聊 -
xmind:
图不错,收藏之。
图中Thread.wait()改用Objec ...
java.lang.Thread.State类详解 -
lahvey:
因为你的$VALUE值是“sed.txt”,并不是这个文件的内 ...
条件控制(test,expr……) -
tomotoboy:
thanks
tr用法
原文地址:http://hi.baidu.com/monalisa88188/blog/item/f5c52122e42ff84dac34de74.html
一、消息队列的基本概念
消息队列是一个存放在内核中的消息链表,每个消息队列由消息队列标识符标识。与管道不同的是消息队列存放在内核中,只有在内核重启(即操作系统重启)或者显示地删除一个消息队列时,该消息队列才会被真正删除。
操作消息队列时,需要用到一些数据结构,熟悉这些数据结构是掌握消息队列的关键。下面介绍几个重要的数据结构。
1、消息缓冲结构
向消息队列发送消息时,必须组成合理的数据结构。Linux系统定义了一个模板数据结构msgbuf:
结构体中的mtype字段代表消息类型。给消息指定类型,可以使得消息在一个队列中重复使用。mtext字段指消息内容。
注意:mtext虽然定义为char类型,并不代表消息只能是一个字符,消息内容可以为任意类型,由用户根据需要定义。如下面就是用户定义的一个消息结构:
消息队列中的消息的大小是受限制的,由<linux/msg.h>中的宏MSGMAX给出消息的最大长度,在实际应用中要注意这个限制。
2、msgqid_ds内核数据结构
Linux内核中,每个消息队列都维护一个结构体msqid_ds,此结构体保存着消息队列当前的状态信息。该结构定义在头文件linux/msg.h中,具体定义如下:
各字段的含义如下:
msg_perm:是一个ipc_perm(定义在头文件linux/ipc.h)的结构,保存了消息队列的存取权限,以及队列的用户ID、组ID等信息。
msg_first:指向队列中的第一条消息
msg_last:指向队列中的最后一条消息
msg_stime:向消息队列发送最后一条信息的时间
msg_rtime:从消息队列取最后一条信息的时间
msg_ctime:最后一次变更消息队列的时间
msg_cbytes:消息队列中所有消息占的字节数
msg_qnum:消息队列中消息的数目
msg_qbytes:消息队列的最大字节数
msg_lspid:向消息队列发送最后一条消息的进程ID
msg_lrpid:从消息队列读取最后一条信息的进程ID
3、ipc_perm:内核数据结构
结构体ipc_perm保存着消息队列的一些重要的信息,比如消息队列关联的键值,消息队列的用户ID、组ID等,它定义在头文件linux/ipc.h中:
几个主要字段的含义如下:
key:创建消息队列用到的键值key
uid:消息队列的用户ID
gid:消息队列的组ID
cuid:创建消息队列的进程用户ID
cgid:创建消息队列的进程组ID
二、消息队列的创建与读写
1、创建消息队列
消息队列是随着内核的存在而存在的,每个消息队列在系统范围内对应惟一的键值。要获得一个消息队列的描述符,只需提供该消息队列的键值即可,该键值通常由函数ftok返回。该函数定义在头文件sys/ipc.h中:
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname,int proj_id);
ftok函数根据pathname和proj_id这两个参数生成惟一的键值。该函数执行成功会返回一个键值,失败返回-1。一个获取键值的例子:
注意:参数pathname在系统中一定要存在且进程有权访问,参数proj_id的取值范围为1~125。
ftok()返回的键值可以提供给函数msgget。msgget()根据这个键值创建一个新的消息队列或者访问一个已存在的消息队列。msgget定义在头文件sys/msg.h中:
int msgget(key_t key,int msgflg);
msgget的参数key即为ftok函数的返回值。msgflg是一个标志参数。以下是msgflg的可能取值。
IPC_CREATE:如果内核中不存在键值与key相等的消息队列,则新建一个消除队列:如果存在这样的消息队列,返回该消息队列的描述符。
IPC_EXCL:和IPC_CREATE一起使用,如果对应键值的消息队列已经存在,则出错,返回-1。
注意:IPC_EXCL单独使用是没有任何意义的。
该函数如果调用成功返回一个消息队列的描述符,否则返回-1。
2、写消息队列
创建一个消息队列后,就可以对消息队列进行读写了。函数msgsnd用于向消息队列发送(写)数据。该函数定义在头文件sys/msg.h中:
int msgsnd(int msgid,struct msgbuf *msgp,size_t msgsz,int msgflg);
msgsnd各参数含义如下:
msgid:函数向msgid标识的消息队列发送一个消息。
msgp:msgp指向发送的消息。
msgsz:要发送的消息的大小,不包含消息类型占用的4个字节。
msgflg:操作标志位。可以设置为0或者IPC_NOWAIT。如果msgflg为0,则当消息队列已满的时候,msgsnd将会阻塞,直到消息可以写进消息队列;如果msgflg为IPC_NOWAIT,当消息队列已满的时候,msgsnd函数将不等待立即返回。
msgsnd函数成功返回0,失败返回-1。常见错误码有:EAGAIN,说明消息队列已满;EIDRM,说明消息队列已被删除;EACCESS,说明无权访问消息队列。
/*写消息*/
3、读消息队列
消息队列中放入数据后,其他进程就可以读取其中的消息了。读取消息的系统调用为msgrcv(),该函数定义在头文件sys/msg.h中,其原型如下:
int msgrcv(int msqid,struct msgbuf *msgp,size_t msgsz,long int msgtyp,int msgflg);
该函数有5个参数,含义如下:
msqid:消息队列描述符。
msgp:读取的消息存储到msgp指向的消息结构中。
msgsz:消息缓冲区的大小。
msgtyp:为请求读取的消息类型。
msgflg:操作标志位。msgflg可以为IPC_NOWAIT,IPC_EXCEPT,IPC_NOERROR3个常量。这些值的意义分别为:
IPC_NOWAIT,如果没有满足条件的消息,调用立即返回,此时错误代码为ENOMSG;
IPC_EXCEPT,与msgtyp配合使用,返回队列中第一个类型不为msgtyp的消息;
IPC_NOERROR,如果队列中满足条件的消息内容大于所请求的msgsz字节,则把该消息截断,截断部分将被丢弃。
调用msgrcv函数的时候,成功会返回消息的实际字节数,否则返回-1。常见的错误码有:E2BIG,表示消息的长度大于msgsz;EIDRM,表示消息队列已被删除;EINVAL,说明msqid无效或msgsz小于0。
/*读消息*/
三、获取和设置消息队列的属性 消息队列的属性保存在系统维护的数据结构msqid_ds中,用户可以通过函数msgctl获取或设置消息队列的属性。msgctl定义在头文件sys/msg.h中,如下:
int msgctl(int msqid,int cmd,struct msqid_ds *buf);
msgctl系统调用对msqid标识的消息队列执行cmd操作,系统定义了3种cmd操作:IPC_STAT,IPC_SET,IPC_RMID,它们的意义如下:
IPC_STAT:该命令用来获取消息队列对应的msqid_ds数据结构,并将其保存到buf指向的地址空间。
IPC_SET:该命令用来设置消息队列的属性,要设置的属性存储在buf中,可设置的属性包括:msg_perm.uid,msg_perm.gid,msg_perm.mode以及msg_qbytes。
IPC_RMID:从内核中删除msqid标识的消息队列。
四、消息队列的应用实例
这里以一个聊天程序为例,进一步展示消息队列的应用。
/*server*/
"client"
一、消息队列的基本概念
消息队列是一个存放在内核中的消息链表,每个消息队列由消息队列标识符标识。与管道不同的是消息队列存放在内核中,只有在内核重启(即操作系统重启)或者显示地删除一个消息队列时,该消息队列才会被真正删除。
操作消息队列时,需要用到一些数据结构,熟悉这些数据结构是掌握消息队列的关键。下面介绍几个重要的数据结构。
1、消息缓冲结构
向消息队列发送消息时,必须组成合理的数据结构。Linux系统定义了一个模板数据结构msgbuf:
#include <linux/msg.h> struct msgbuf{ long mtype; char mtext[1]; };
结构体中的mtype字段代表消息类型。给消息指定类型,可以使得消息在一个队列中重复使用。mtext字段指消息内容。
注意:mtext虽然定义为char类型,并不代表消息只能是一个字符,消息内容可以为任意类型,由用户根据需要定义。如下面就是用户定义的一个消息结构:
struct myMsgbuf{ long mtype; struct student stu; };
消息队列中的消息的大小是受限制的,由<linux/msg.h>中的宏MSGMAX给出消息的最大长度,在实际应用中要注意这个限制。
2、msgqid_ds内核数据结构
Linux内核中,每个消息队列都维护一个结构体msqid_ds,此结构体保存着消息队列当前的状态信息。该结构定义在头文件linux/msg.h中,具体定义如下:
struct msqid_ds{ struct_ipc_perm msg_perm; struct_msg *msg_first; struct_msg *msg_last; __kernel_t time_t msg_stime; __kernel_t time_t msg_rtime; __kernel_t time_t msg_ctime; unsigned long msg_lcbytes; unsigned long msg_lqbytes; unsigned short msg_cbytes; unsigned short msg_qnum; unsigned short msg_qbytes; __kernel_ipc_pid_t msg_lspid; __kernel_ipc_pid_t msg_lrpid; };
各字段的含义如下:
msg_perm:是一个ipc_perm(定义在头文件linux/ipc.h)的结构,保存了消息队列的存取权限,以及队列的用户ID、组ID等信息。
msg_first:指向队列中的第一条消息
msg_last:指向队列中的最后一条消息
msg_stime:向消息队列发送最后一条信息的时间
msg_rtime:从消息队列取最后一条信息的时间
msg_ctime:最后一次变更消息队列的时间
msg_cbytes:消息队列中所有消息占的字节数
msg_qnum:消息队列中消息的数目
msg_qbytes:消息队列的最大字节数
msg_lspid:向消息队列发送最后一条消息的进程ID
msg_lrpid:从消息队列读取最后一条信息的进程ID
3、ipc_perm:内核数据结构
结构体ipc_perm保存着消息队列的一些重要的信息,比如消息队列关联的键值,消息队列的用户ID、组ID等,它定义在头文件linux/ipc.h中:
struct ipc_perm{ __kernel_key_t key; __kernel_uid_t uid; __kernel_gid_t gid; __kernel_uid_t cuid; __kernel_gid_t cgid; __kernel_mode_t mode; unsigned_short seg; };
几个主要字段的含义如下:
key:创建消息队列用到的键值key
uid:消息队列的用户ID
gid:消息队列的组ID
cuid:创建消息队列的进程用户ID
cgid:创建消息队列的进程组ID
二、消息队列的创建与读写
1、创建消息队列
消息队列是随着内核的存在而存在的,每个消息队列在系统范围内对应惟一的键值。要获得一个消息队列的描述符,只需提供该消息队列的键值即可,该键值通常由函数ftok返回。该函数定义在头文件sys/ipc.h中:
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname,int proj_id);
ftok函数根据pathname和proj_id这两个参数生成惟一的键值。该函数执行成功会返回一个键值,失败返回-1。一个获取键值的例子:
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> int main(void) { int i; for(i = 1;i <= 5;i++) printf("key[%d] = %ul \n",i,ftok(".",i)); exit(0); }
注意:参数pathname在系统中一定要存在且进程有权访问,参数proj_id的取值范围为1~125。
ftok()返回的键值可以提供给函数msgget。msgget()根据这个键值创建一个新的消息队列或者访问一个已存在的消息队列。msgget定义在头文件sys/msg.h中:
int msgget(key_t key,int msgflg);
msgget的参数key即为ftok函数的返回值。msgflg是一个标志参数。以下是msgflg的可能取值。
IPC_CREATE:如果内核中不存在键值与key相等的消息队列,则新建一个消除队列:如果存在这样的消息队列,返回该消息队列的描述符。
IPC_EXCL:和IPC_CREATE一起使用,如果对应键值的消息队列已经存在,则出错,返回-1。
注意:IPC_EXCL单独使用是没有任何意义的。
该函数如果调用成功返回一个消息队列的描述符,否则返回-1。
2、写消息队列
创建一个消息队列后,就可以对消息队列进行读写了。函数msgsnd用于向消息队列发送(写)数据。该函数定义在头文件sys/msg.h中:
int msgsnd(int msgid,struct msgbuf *msgp,size_t msgsz,int msgflg);
msgsnd各参数含义如下:
msgid:函数向msgid标识的消息队列发送一个消息。
msgp:msgp指向发送的消息。
msgsz:要发送的消息的大小,不包含消息类型占用的4个字节。
msgflg:操作标志位。可以设置为0或者IPC_NOWAIT。如果msgflg为0,则当消息队列已满的时候,msgsnd将会阻塞,直到消息可以写进消息队列;如果msgflg为IPC_NOWAIT,当消息队列已满的时候,msgsnd函数将不等待立即返回。
msgsnd函数成功返回0,失败返回-1。常见错误码有:EAGAIN,说明消息队列已满;EIDRM,说明消息队列已被删除;EACCESS,说明无权访问消息队列。
/*写消息*/
#include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/msg.h> #define BUF_SIZE 256 #define PROJ_ID 32 #define PATH_NAME "." int main(void){ struct mymsgbuf{ long msgtype; char ctrlstring[BUF_SIZE]; } msgbuffer; int qid; int msglen; key_t msgkey; /*get key value*/ if((msgkey=ftok(PATH_NAME,PROJ_ID))==-1) { perror("ftok error!\n"); exit(1); } /*creat message queue*/ if((qid=msgget(msgkey,IPC_CREAT|0660))==-1) { perror("msgget error!\n"); } /*fill message struct, and send the message*/ msgbuffer.msgtype=3; strcpy(msgbuffer.ctrlstring,"Hello,message queue"); msglen=sizeof(struct mymsgbuf)- sizeof(long); if(msgsnd(qid,&msgbuffer,msglen,0)==-1) { perror("msgget error!\n"); exit(1); } exit(0); }
3、读消息队列
消息队列中放入数据后,其他进程就可以读取其中的消息了。读取消息的系统调用为msgrcv(),该函数定义在头文件sys/msg.h中,其原型如下:
int msgrcv(int msqid,struct msgbuf *msgp,size_t msgsz,long int msgtyp,int msgflg);
该函数有5个参数,含义如下:
msqid:消息队列描述符。
msgp:读取的消息存储到msgp指向的消息结构中。
msgsz:消息缓冲区的大小。
msgtyp:为请求读取的消息类型。
msgflg:操作标志位。msgflg可以为IPC_NOWAIT,IPC_EXCEPT,IPC_NOERROR3个常量。这些值的意义分别为:
IPC_NOWAIT,如果没有满足条件的消息,调用立即返回,此时错误代码为ENOMSG;
IPC_EXCEPT,与msgtyp配合使用,返回队列中第一个类型不为msgtyp的消息;
IPC_NOERROR,如果队列中满足条件的消息内容大于所请求的msgsz字节,则把该消息截断,截断部分将被丢弃。
调用msgrcv函数的时候,成功会返回消息的实际字节数,否则返回-1。常见的错误码有:E2BIG,表示消息的长度大于msgsz;EIDRM,表示消息队列已被删除;EINVAL,说明msqid无效或msgsz小于0。
/*读消息*/
#include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/msg.h> #define BUF_SIZE 256 #define PROJ_ID 32 #define PATH_NAME "." int main(void) { struct mymsgbuf{ long msgtype; char ctrlstring[BUF_SIZE]; } msgbuffer; int qid; int msglen; key_t msgkey; if((msgkey=ftok(PATH_NAME,PROJ_ID))==-1) { perror("ftok error!\n"); exit(1); } if((qid=msgget(msgkey,IPC_CREAT|0660))==-1) { perror("msgget error!\n"); exit(1); } msglen=sizeof(struct mymsgbuf)- sizeof(long); if(msgrcv(qid,&msgbuffer,msglen,3.0)==-1) { perror("msgrcv error!\n"); exit(1); } printf("Get message: %s\n", msgbuffer.ctrlstring); exit(0); }
三、获取和设置消息队列的属性 消息队列的属性保存在系统维护的数据结构msqid_ds中,用户可以通过函数msgctl获取或设置消息队列的属性。msgctl定义在头文件sys/msg.h中,如下:
int msgctl(int msqid,int cmd,struct msqid_ds *buf);
msgctl系统调用对msqid标识的消息队列执行cmd操作,系统定义了3种cmd操作:IPC_STAT,IPC_SET,IPC_RMID,它们的意义如下:
IPC_STAT:该命令用来获取消息队列对应的msqid_ds数据结构,并将其保存到buf指向的地址空间。
IPC_SET:该命令用来设置消息队列的属性,要设置的属性存储在buf中,可设置的属性包括:msg_perm.uid,msg_perm.gid,msg_perm.mode以及msg_qbytes。
IPC_RMID:从内核中删除msqid标识的消息队列。
#include <stdio.h> #include <stdlib.h> #include <sys/ipc.h> #include <sys/msg.h> #define BUF_SIZE 256 #define PROJ_ID 32 #define PATH_NAME "." void getmsgattr(int msgid,struct msqid_ds msq_info); int main(void) { /* */ struct mymsgbuf{ long msgtype; char ctrlstring[BUF_SIZE]; } msgbuffer; int qid; int msglen; key_t msgkey; struct msqid_ds msg_attr; /*获取键值*/ if((msgkey=ftok(PATH_NAME,PROJ_ID))==-1) { perror("ftok error!\n"); exit(1); } /*获取消息队列标识符*/ if((qid=msgget(msgkey,IPC_CREAT|0660))==-1) { perror("msgget error!\n"); exit(1); } getmsgattr(qid,msg_attr); /*输出消息队列的属性*/ /*发送一条消息到消息队列*/ msgbuffer.msgtype=2; strcpy(msgbuffer.ctrlstring,"Another message"); msglen=sizeof(struct mymsgbuf)- sizeof(long); if(msgsnd(qid,&msgbuffer,msglen,0)==-1) { perror("msgget error!\n"); exit(1); } getmsgattr(qid,msg_attr); /*再输出消息队列的属性*/ /*设置消息队列的属性*/ msg_attr.msg_perm.uid = 8; msg_attr.msg_perm.gid = 8; if (msgctl(qid,IPC_SET,&msg_attr) == -1) { perror("msg set error!\n"); exit(1); } getmsgattr(qid,msg_attr);/*修改后再观察其属性*/ if (msgctl(qid,IPC_RMID,NULL) == -1) { perror("delete msg error!\n"); exit(1); } getmsgattr(qid,msg_attr);/*删除后再观察其属性*/ } void getmsgattr(int msgid,struct msqid_ds msg_info) { if (msgctl(msgid,IPC_STAT,&msg_info) == -1) { perror("msgctl error!\n"); return; } printf("***information of message queue %d***\n",msgid); printf("last msgsnd to msq time is %s\n",ctime(&(msg_info.msg_stime))); printf("last msgrcv time from msg is %s\n",ctime(&(msg_info.msg_rtime))); printf("last change msg time is %s\n",ctime(&(msg_info.msg_ctime))); printf("current number of bytes on queue is %d\n",msg_info.msg_cbytes); printf("number of messages in queue is %d\n",msg_info.msg_qnum); printf("max number of bytes on queue is %d\n",msg_info.msg_qbytes); printf("pid of last msgsnd is %d\n",msg_info.msg_lspid); printf("pid of last msgrcv is %d\n",msg_info.msg_lrpid); printf("msg uid is %d\n",msg_info.msg_perm.uid); printf("msg gid is %d\n",msg_info.msg_perm.gid); printf("*******information end!**************\n",msgid); }以上是对消息队列进行操作前的属性。发送消息后和重新设置后的消息队列属性都会因为操作而改变。可以运行程序观察全部的输出结果,对比操作前后消息队列属性是如何改变的。
四、消息队列的应用实例
这里以一个聊天程序为例,进一步展示消息队列的应用。
/*server*/
#include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/stat.h> #define BUF_SIZE 256 #define PROJ_ID 32 #define PATH_NAME "/tmp" #define SERVER_MSG 1 #define CLIENT_MSG 2 int main(void){ /*用户自定义消息缓冲区*/ struct mymsgbuf{ long msgtype; char ctrlstring[BUF_SIZE]; } msgbuffer; int qid; int msglen; key_t msgkey; /*获取键值*/ if((msgkey=ftok(PATH_NAME,PROJ_ID))==-1) { perror("ftok error!\n"); exit(1); } /*获取消息队列标识符*/ if ((qid = msgget(msgkey,IPC_CREAT|0660)) == -1) { perror("msgget error!\n"); exit(1); } while(1) { printf("server:"); fgets(msgbuffer.ctrlstring,BUF_SIZE, stdin); if(strncmp("exit",msgbuffer.ctrlstring,4)==0) { msgctl(qid,IPC_RMID,NULL); break; } msgbuffer.ctrlstring[strlen(msgbuffer.ctrlstring) - 1] = '\0'; msgbuffer.msgtype = SERVER_MSG; if (msgsnd(qid,&msgbuffer,strlen(msgbuffer.ctrlstring) + 1,0) == -1) { perror("Server msgsnd error!\n"); exit(1); } if (msgrcv(qid,&msgbuffer,BUF_SIZE,CLIENT_MSG,0) == -1) { perror("Server msgrcv error!\n"); exit(1); } printf("Client: %s\n",msgbuffer.ctrlstring); } exit(0); }
"client"
#include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/stat.h> #define BUF_SIZE 256 #define PROJ_ID 32 #define PATH_NAME "/tmp" #define SERVER_MSG 1 #define CLIENT_MSG 2 int main(void) { /*用户自定义消息缓冲区*/ struct mymsgbuf{ long msgtype; char ctrlstring[BUF_SIZE]; }msgbuffer; int qid;/*消息队列标识符*/ int msglen; key_t msgkey; /*获取键值*/ if ((msgkey = ftok(PATH_NAME,PROJ_ID)) == -1) { perror("ftok error!\n"); exit(1); } if ((qid = msgget(msgkey,IPC_CREAT|0660)) == -1) { perror("msgget error!\n"); exit(1); } while(1) { if (msgrcv(qid,&msgbuffer,BUF_SIZE,SERVER_MSG,0) == -1) /*if queue is empty, block here*/ { perror("Server msgrcv error!\n"); exit(1); } printf("server: %s\n",msgbuffer.ctrlstring); printf("client:"); fgets(msgbuffer.ctrlstring,BUF_SIZE,stdin); if (strncmp("exit",msgbuffer.ctrlstring,4) == 0) { break; } msgbuffer.ctrlstring[strlen(msgbuffer.ctrlstring)-1] = '\0'; msgbuffer.msgtype = CLIENT_MSG; if (msgsnd(qid,&msgbuffer,strlen(msgbuffer.ctrlstring) + 1,0) == -1) { perror("client msgsnd error!\n"); exit(1); } } exit(0); }
发表评论
-
Berkeley套接字的一些基本知识
2009-10-25 00:46 4273一、首先看一下Berkeley S ... -
进程间通信——共享内存
2009-10-18 15:02 4996共享内存(Shared Memory) 共享内存,简单的说就是 ... -
进程间通信——信号量
2009-10-16 15:35 3913有关结构体 1.sem struct sem { ... -
linux/unix锁
2009-10-07 19:54 2670锁定中的几个概念 ... -
文件共享
2009-08-14 14:58 1700UNIX支持在不同进程间共 ... -
文件I/O
2009-08-13 02:06 1231本文将对UNIX系统的文件 ... -
进程间通信——管道
2009-08-13 00:02 17941.匿名管道 匿名管道创建的四种方法 使用pipe()函数 ... -
进程间通信——系统调用setjmp()与longjmp()
2009-08-10 23:05 2655系统调用setjmp()和 longjmp() 有时候,当接收 ... -
进程间通信——信号
2009-08-10 13:21 3512信号类型 信号类型在Trap命令详解中有详细的介绍 信号捕捉 ... -
进程控制——进程环境
2009-08-09 14:49 1225进程环境 进程的环境是一个以 NULL 字符结尾的字符串之集合 ... -
gcc编译器入门
2009-08-07 18:51 1217Gcc编译流程: 预处理(Pre-Processing); ... -
Makefile文件的制作
2009-08-07 15:29 1696当我们有很多C源文件的时候,我们每次运行都要对其编译、链接…… ... -
unix下第一个C程序
2009-08-07 14:53 1024首先我们的目录下有两个C程序,功能很简单就是求一个整数的阶乘 ... -
UNIX 进程揭秘——探索运行在 UNIX 操作系统下的进程的生命周期
2009-08-03 10:40 1091原文地址:http://www.ibm.com/develop ... -
unix进程(初识)
2009-07-28 17:24 1359原文地址:http://blog.chinaunix.net/ ... -
linux进程
2009-07-28 16:49 1188原文地址:http://it.china- ...
相关推荐
内容概要:本文详细介绍了基于MATLAB GUI界面和卷积神经网络(CNN)的模糊车牌识别系统。该系统旨在解决现实中车牌因模糊不清导致识别困难的问题。文中阐述了整个流程的关键步骤,包括图像的模糊还原、灰度化、阈值化、边缘检测、孔洞填充、形态学操作、滤波操作、车牌定位、字符分割以及最终的字符识别。通过使用维纳滤波或最小二乘法约束滤波进行模糊还原,再利用CNN的强大特征提取能力完成字符分类。此外,还特别强调了MATLAB GUI界面的设计,使得用户能直观便捷地操作整个系统。 适合人群:对图像处理和深度学习感兴趣的科研人员、高校学生及从事相关领域的工程师。 使用场景及目标:适用于交通管理、智能停车场等领域,用于提升车牌识别的准确性和效率,特别是在面对模糊车牌时的表现。 其他说明:文中提供了部分关键代码片段作为参考,并对实验结果进行了详细的分析,展示了系统在不同环境下的表现情况及其潜在的应用前景。
嵌入式八股文面试题库资料知识宝典-计算机专业试题.zip
嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_3.zip
内容概要:本文深入探讨了一款额定功率为4kW的开关磁阻电机,详细介绍了其性能参数如额定功率、转速、效率、输出转矩和脉动率等。同时,文章还展示了利用RMxprt、Maxwell 2D和3D模型对该电机进行仿真的方法和技术,通过外电路分析进一步研究其电气性能和动态响应特性。最后,文章提供了基于RMxprt模型的MATLAB仿真代码示例,帮助读者理解电机的工作原理及其性能特点。 适合人群:从事电机设计、工业自动化领域的工程师和技术人员,尤其是对开关磁阻电机感兴趣的科研工作者。 使用场景及目标:适用于希望深入了解开关磁阻电机特性和建模技术的研究人员,在新产品开发或现有产品改进时作为参考资料。 其他说明:文中提供的代码示例仅用于演示目的,实际操作时需根据所用软件的具体情况进行适当修改。
少儿编程scratch项目源代码文件案例素材-剑客冲刺.zip
少儿编程scratch项目源代码文件案例素材-几何冲刺 转瞬即逝.zip
内容概要:本文详细介绍了基于PID控制器的四象限直流电机速度驱动控制系统仿真模型及其永磁直流电机(PMDC)转速控制模型。首先阐述了PID控制器的工作原理,即通过对系统误差的比例、积分和微分运算来调整电机的驱动信号,从而实现转速的精确控制。接着讨论了如何利用PID控制器使有刷PMDC电机在四个象限中精确跟踪参考速度,并展示了仿真模型在应对快速负载扰动时的有效性和稳定性。最后,提供了Simulink仿真模型和详细的Word模型说明文档,帮助读者理解和调整PID控制器参数,以达到最佳控制效果。 适合人群:从事电力电子与电机控制领域的研究人员和技术人员,尤其是对四象限直流电机速度驱动控制系统感兴趣的读者。 使用场景及目标:适用于需要深入了解和掌握四象限直流电机速度驱动控制系统设计与实现的研究人员和技术人员。目标是在实际项目中能够运用PID控制器实现电机转速的精确控制,并提高系统的稳定性和抗干扰能力。 其他说明:文中引用了多篇相关领域的权威文献,确保了理论依据的可靠性和实用性。此外,提供的Simulink模型和Word文档有助于读者更好地理解和实践所介绍的内容。
嵌入式八股文面试题库资料知识宝典-2013年海康威视校园招聘嵌入式开发笔试题.zip
少儿编程scratch项目源代码文件案例素材-驾驶通关.zip
小区开放对周边道路通行能力影响的研究.pdf
内容概要:本文探讨了冷链物流车辆路径优化问题,特别是如何通过NSGA-2遗传算法和软硬时间窗策略来实现高效、环保和高客户满意度的路径规划。文中介绍了冷链物流的特点及其重要性,提出了软时间窗概念,允许一定的配送时间弹性,同时考虑碳排放成本,以达到绿色物流的目的。此外,还讨论了如何将客户满意度作为路径优化的重要评价标准之一。最后,通过一段简化的Python代码展示了遗传算法的应用。 适合人群:从事物流管理、冷链物流运营的专业人士,以及对遗传算法和路径优化感兴趣的科研人员和技术开发者。 使用场景及目标:适用于冷链物流企业,旨在优化配送路线,降低运营成本,减少碳排放,提升客户满意度。目标是帮助企业实现绿色、高效的物流配送系统。 其他说明:文中提供的代码仅为示意,实际应用需根据具体情况调整参数设置和模型构建。
少儿编程scratch项目源代码文件案例素材-恐怖矿井.zip
内容概要:本文详细介绍了基于STM32F030的无刷电机控制方案,重点在于高压FOC(磁场定向控制)技术和滑膜无感FOC的应用。该方案实现了过载、过欠压、堵转等多种保护机制,并提供了完整的源码、原理图和PCB设计。文中展示了关键代码片段,如滑膜观测器和电流环处理,以及保护机制的具体实现方法。此外,还提到了方案的移植要点和实际测试效果,确保系统的稳定性和高效性。 适合人群:嵌入式系统开发者、电机控制系统工程师、硬件工程师。 使用场景及目标:适用于需要高性能无刷电机控制的应用场景,如工业自动化设备、无人机、电动工具等。目标是提供一种成熟的、经过验证的无刷电机控制方案,帮助开发者快速实现并优化电机控制性能。 其他说明:提供的资料包括详细的原理图、PCB设计文件、源码及测试视频,方便开发者进行学习和应用。
基于有限体积法Godunov格式的管道泄漏检测模型研究.pdf
嵌入式八股文面试题库资料知识宝典-CC++笔试题-深圳有为(2019.2.28)1.zip
少儿编程scratch项目源代码文件案例素材-几何冲刺 V1.5.zip
Android系统开发_Linux内核配置_USB-HID设备模拟_通过root权限将Android设备转换为全功能USB键盘的项目实现_该项目需要内核支持configFS文件系统
C# WPF - LiveCharts Project
少儿编程scratch项目源代码文件案例素材-恐怖叉子 动画.zip
嵌入式八股文面试题库资料知识宝典-嵌⼊式⼯程师⾯试⾼频问题.zip