mg4155com > mg4155线路检测手机版 > Nuttx消息队列机制,从零开首邮件服务器搭建

原标题:Nuttx消息队列机制,从零开首邮件服务器搭建

浏览次数:110 时间:2019-10-04

MySQL:存取顾客消息,监听的域名消息,客商邮箱地址以及登陆密码等.

  1. 认清是还是不是在行车制动器踏板里下文中,由于sem_wait()恐怕接触职务调整,产生自己睡眠,由此无法在制动踏板的里面下文中调用;
  2. 一旦时域信号量可用,将计数值减1,并将调用职责增添到模拟信号量的持有者链表中;
  3. 假如功率信号量不可用,将计数值减1,将调用职务中waitsem值设置成当前时限信号量。假若使能了优先级承接,则升迁该信号量持有者中比当前调用任务优先级低的天职优先级。最终将调用任务增添到非实信号量等待队列g_waitingforsemaphore中。
  1. 水源完成数据结构

该接口将msg信息增多到mqdes音讯队列中,msglen钦命了音信的字节长度,这几个尺寸不能够当先mq_getattr()接口中拿走的最大尺寸。借使音讯队列未满,mq_send()会将msg放置到prio点名的新闻队列中。高优先级的新闻会插在低优先级消息在此之前。prio的值不能够超过MQ_PRIO_MAX。纵然音信队列已满,并且O_NONBLOCK不曾安装,mq_send()会直接不通,直到新闻队列有空中去存放音讯。假使NON_BLOCK设置了,那么新闻将不会入列,况兼会重返错误码。

tools目录下富含了二种四种的剧本和Host C程序,那一个都以Nuttx编写翻译系统的必不可少的有个别。README.txt有详实的牵线。

Makefile.unix才是大家的主干,上述所介绍的公文,最终都要为它所用,直接看代码吧。

IMAP, Internet Message Access Protocol, 直译过来正是网络音讯访问合同,大概和昨日主流的翻译不太一致,但是能知晓其意思就好.相对于pop3合计抱有邮件的管制都亟需下载下来进而管理,IMAP提供了顾客远程访谈邮件服务器的门径,因此通过IMAP,客户能够一贯保管邮件服务器上的邮件.

/**************************************************************************** * Name: sem_post * * Description: * When a task has finished with a semaphore, it will call sem_post(). * This function unlocks the semaphore referenced by sem by performing the * semaphore unlock operation on that semaphore. * * If the semaphore value resulting from this operation is positive, then * no tasks were blocked waiting for the semaphore to become unlocked; the * semaphore is simply incremented. * * If the value of the semaphore resulting from this operation is zero, * then one of the tasks blocked waiting for the semaphore shall be * allowed to return successfully from its call to sem_wait(). * * Parameters: * sem - Semaphore descriptor * * Return Value: * 0  or -1  if unsuccessful * * Assumptions: * This function may be called from an interrupt handler. * ****************************************************************************/int sem_post(FAR sem_t *sem){ FAR struct tcb_s *stcb = NULL; irqstate_t flags; int ret = ERROR; /* Make sure we were supplied with a valid semaphore. */ if  { /* The following operations must be performed with interrupts * disabled because sem_post() may be called from an interrupt * handler. */ flags = enter_critical_section(); /* Perform the semaphore unlock operation, releasing this task as a * holder then also incrementing the count on the semaphore. * * NOTE: When semaphores are used for signaling purposes, the holder * of the semaphore may not be this thread! In this case, * sem_releaseholder() will do nothing. * * In the case of a mutex this could be simply resolved since there is * only one holder but for the case of counting semaphores, there may * be many holders and if the holder is not this thread, then it is * not possible to know which thread/holder should be released. * * For this reason, it is recommended that priority inheritance be * disabled via sem_setprotocol(SEM_PRIO_NONE) when the semahore is * initialixed if the semaphore is to used for signaling purposes. */ ASSERT(sem->semcount < SEM_VALUE_MAX); sem_releaseholder; sem->semcount++;#ifdef CONFIG_PRIORITY_INHERITANCE /* Don't let any unblocked tasks run until we complete any priority * restoration steps. Interrupts are disabled, but we do not want * the head of the read-to-run list to be modified yet. * * NOTE: If this sched_lock is called from an interrupt handler, it * will do nothing. */ sched_lock();#endif /* If the result of of semaphore unlock is non-positive, then * there must be some task waiting for the semaphore. */ if (sem->semcount <= 0) { /* Check if there are any tasks in the waiting for semaphore * task list that are waiting for this semaphore. This is a * prioritized list so the first one we encounter is the one * that we want. */ for (stcb = (FAR struct tcb_s *)g_waitingforsemaphore.head; (stcb && stcb->waitsem != sem); stcb = stcb->flink); if (stcb != NULL) { /* The task will be the new holder of the semaphore when * it is awakened. */ sem_addholder_tcb(stcb, sem); /* It is, let the task take the semaphore */ stcb->waitsem = NULL; /* Restart the waiting task. */ up_unblock_task; } } /* Check if we need to drop the priority of any threads holding * this semaphore. The priority could have been boosted while they * held the semaphore. */#ifdef CONFIG_PRIORITY_INHERITANCE sem_restorebaseprio(stcb, sem); sched_unlock();#endif ret = OK; /* Interrupts may now be enabled. */ leave_critical_section; } else { set_errno; } return ret;}
  1. 顾客方式专门的学问行列

mq_timedsend()/mq_timedreceive()接口完毕跟mq_send()/mq_receive()着力类似,独一不一致的是加多了五个按时的效果与利益,而以此定期的意义是经过watchdog来实现的。在Nuttx中,看门狗以linked list全局队列的样式来爱戴,创造多个看门狗后,会增多进全局队列中,然后会在Timer停顿管理中去调用wd_timer()接口,以咬定看门狗的时刻是还是不是到期,若是届时了就去实施注册进看门狗中的回调函数。mq_rcvtimeout()/mq_sndtimeout()接口正是用来被登记到看门狗的回调函数。当设定的大运到期了后,在制动踏板的里面下文中回调那七个函数,而那五个函数都会调用到mq_waitirq(),在mq_waitirq()接口中,会去清空struct tcb_s结构中的msgwaitq队列,并将该音信队列中等待的数值减1,并设置错误状态,然后还原该任务的实行。(Task在调用mq_timedsend()/mq_timedreceive()时,在岁月未到期时会先上床等待,那时候间到期后,在看门狗的回调函数中去苏醒该职责继续试行)关键代码如下:

build|-nuttx| || - Makefile|-apps| || - Makefile

PTR:反向域名剖判,能够经过发件人的IP地址反向得知域名,也是一种用于剖断发件人是不是健康的格局.

  • 优先级承袭
  1. 顾客数据结构
TOPDIR := ${shell pwd | sed -e 's/ /\ /g'}-include $/.configinclude $/tools/Config.mk-include $/Make.defs# 可以通过“make V=1”的形式来选择不同的编译方式,其中V=1/2时,会使能命令的回显,而在Makefile中“@”可以控制命令不回显。# Control build verbosity## V=1,2: Enable echo of commands# V=2: Enable bug/verbose options in tools and scriptsifeq export Q :=elseifeq export Q :=elseexport Q := @endifendif# Default tools# 定义符号链接和断开链接的宏ifeq ($,)DIRLINK = $/tools/link.shDIRUNLINK = $/tools/unlink.shendif# This define is passed as EXTRADEFINES for kernel-mode builds. It is also passed# during PASS1 (but not PASS2) context and depend targets.KDEFINE = ${shell $/tools/define.sh "$" __KERNEL__}# Process architecture and board-specific directories#架构和板级相关的目录宏定义ARCH_DIR = arch/$(CONFIG_ARCH)ARCH_SRC = $/srcARCH_INC = $/includeifeq ($(CONFIG_ARCH_BOARD_CUSTOM),y)ifeq ($(CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH),y)BOARD_DIR = $$$(CONFIG_ARCH_BOARD_CUSTOM_DIR)elseBOARD_DIR = $(CONFIG_ARCH_BOARD_CUSTOM_DIR)endifelseBOARD_DIR = $$configs/hobot$$(CONFIG_ARCH_BOARD)endif# CONFIG_APPS_DIR can be over-ridden from the command line or in the .config file.# The default value of CONFIG_APPS_DIR is ../apps. Ultimately, the application# will be built if APPDIR is defined. APPDIR will be defined if a directory containing# a Makefile is found at the path provided by CONFIG_APPS_DIR# 当在CONFIG_APPS_DIR路径中存在Makefile时,APPDIR才会被定义ifeq ($(CONFIG_APPS_DIR),)CONFIG_APPS_DIR = ../appsendifAPPDIR := ${shell if [ -r $(CONFIG_APPS_DIR)/Makefile ]; then echo "$(CONFIG_APPS_DIR)"; fi}# Add-on directories. These may or may not be in place in the# NuttX source tree (they must be specifically installed)## NUTTX_ADDONS is the list of directories built into the NuttX kernel.# USER_ADDONS is the list of directories that will be built into the user# application## FSDIRS depend on file descriptor support; NONFSDIRS do not (except for parts# of FSDIRS). We will exclude FSDIRS from the build if file descriptor# support is disabled# CONTEXTDIRS include directories that have special, one-time pre-build# requirements. Normally this includes things like auto-generation of# configuration specific files or creation of configurable symbolic links# USERDIRS - When NuttX is build is a monolithic kernel, this provides the# list of directories that must be built# OTHERDIRS - These are directories that are not built but probably should# be cleaned to prevent garbage from collecting in them when changing# configurations.## CLEANDIRS are the directories that will clean in. These are# all directories that we know about.# KERNDEPDIRS are the directories in which we will build target dependencies.# If NuttX and applications are built separately (CONFIG_BUILD_PROTECTED or# CONFIG_BUILD_KERNEL), then this holds only the directories containing# kernel files.# USERDEPDIRS. If NuttX and applications are built separately (CONFIG_BUILD_PROTECTED),# then this holds only the directories containing user files. If# CONFIG_BUILD_KERNEL is selected, then applications are not build at all.# 定义了一系列文件夹相关的宏include Directories.mk## Extra objects used in the final link.## Pass 1 1ncremental  link objects should be put into the# processor-specific source directory (where other link objects will# be created). If the pass1 object is an archive, it could go anywhere.ifeq ($(CONFIG_BUILD_2PASS),y)EXTRA_OBJS += $(CONFIG_PASS1_OBJECT)endif# Library build selections## NUTTXLIBS is the list of NuttX libraries that is passed to the# processor-specific Makefile to build the final NuttX target.# Libraries in FSDIRS are excluded if file descriptor support# is disabled.# USERLIBS is the list of libraries used to build the final user-space# application# EXPORTLIBS is the list of libraries that should be exported by# 'make export' isifeq ($(CONFIG_BUILD_PROTECTED),y)include ProtectedLibs.mkelseifeq ($(CONFIG_BUILD_KERNEL),y)include KernelLibs.mkelseinclude FlatLibs.mkendifendif# LINKLIBS derives from NUTTXLIBS and is simply the same list with the# subdirectory removed#LINKLIBS链接库和NUTTXLIBS是一样的,只是通过patsubst将子目录lib去掉了而已LINKLIBS = $(patsubst lib/%,%,$(NUTTXLIBS))# Export tool definitions#用于'make export'MKEXPORT= tools/mkexport.shMKEXPORT_ARGS = -w$ -t "$"ifeq ($(CONFIG_BUILD_PROTECTED),y)MKEXPORT_ARGS += -uelseifeq ($(CONFIG_BUILD_KERNEL),y)MKEXPORT_ARGS += -uendifendififeq MKEXPORT_ARGS += -dendif# This is the name of the final target (relative to the top level directorty)NUTTXNAME = nuttxBIN = $(NUTTXNAME)$#编译的最终目标:nuttx, .PHONY用来声明伪目标all: $.PHONY: dirlinks context clean_context check_context export subdir_clean clean subdir_distclean distclean apps_clean apps_distclean#头文件:math.h、float.h、stdarg.h,在不同的平台中可能有不同的实现# Target used to copy include/nuttx/lib/math.h. If CONFIG_ARCH_MATH_H is# defined, then there is an architecture specific math.h header file# that will be included indirectly from include/math.h. But first, we# have to copy math.h from include/nuttx/. to include/. Logic within# include/nuttx/lib/math.h will hand the redirection to the architecture-# specific math.h header file.## If the CONFIG_LIBM is defined, the Rhombus libm will be built at libc/math.# Definitions and prototypes for the Rhombus libm are also contained in# include/nuttx/lib/math.h and so the file must also be copied in that case.## If neither CONFIG_ARCH_MATH_H nor CONFIG_LIBM is defined, then no math.h# header file will be provided. You would want that behavior if  you# don't use libm, or  you want to use the math.h and libm provided# within your toolchain.ifeq ($(CONFIG_ARCH_MATH_H),y)NEED_MATH_H = yelseifeq ($(CONFIG_LIBM),y)NEED_MATH_H = yendifendififeq ($(NEED_MATH_H),y)include/math.h: include/nuttx/lib/math.h $ cp -f include/nuttx/lib/math.h include/math.helseinclude/math.h:endif# The float.h header file defines the properties of your floating point# implementation. It would always be best to use your toolchain's float.h# header file but if none is available, a default float.h header file will# provided if this option is selected. However there is no assurance that# the settings in this float.h are actually correct for your platform!ifeq ($(CONFIG_ARCH_FLOAT_H),y)include/float.h: include/nuttx/lib/float.h $ cp -f include/nuttx/lib/float.h include/float.helseinclude/float.h:endif# Target used to copy include/nuttx/lib/stdarg.h. If CONFIG_ARCH_STDARG_H is# defined, then there is an architecture specific stdarg.h header file# that will be included indirectly from include/lib/stdarg.h. But first, we# have to copy stdarg.h from include/nuttx/. to include/.ifeq ($(CONFIG_ARCH_STDARG_H),y)include/stdarg.h: include/nuttx/lib/stdarg.h $ cp -f include/nuttx/lib/stdarg.h include/stdarg.helseinclude/stdarg.h:endif# Targets used to build include/nuttx/version.h. Creation of version.h is# part of the overall NuttX configuration sequence. Notice that the# tools/mkversion tool is built and used to create include/nuttx/version.h# 先编译mkversion工具,再用该工具来创建version.h文件。下行make命令中,-C后边指定需要执行make的路径,此处指tools目录,# -f指定Makefile文件,此处指Makefile.host,并将TOPDIR这个宏的值传递给Makefile.unix,make的目标是mkversion$(HOSTEXEEXT)# 当make命令中带有多个参数时,注意'-'和'='等特殊符号,没特殊符号约束的就是make的目标,比如此处的mkversion$(HOSTEXEEXT)tools/mkversion$(HOSTEXEEXT): $ $ -C tools -f Makefile.host TOPDIR="$" mkversion$(HOSTEXEEXT)# 查看是否存在.version文件$/.version: $ if [ ! -f .version ]; then  echo "No .version file found, creating one";  tools/version.sh -v 0.0 -b 0 .version;  chmod 755 .version;  fi# 创建version.h文件include/nuttx/version.h: $/.version tools/mkversion$(HOSTEXEEXT) $ tools/mkversion $ > include/nuttx/version.h# ROMFS,其中rcS.template为启动脚本,nsh_romfsimg.h是根据这个启动脚本而产生的头部信息arch/arm/include/board/nsh_romfsimg.h:ifeq ($(CONFIG_NSH_ARCHROMFS),y) $ if [ ! -f $(BOARD_DIR)/include/rcS.template ]; then  echo "No rcS.template file create it!!!!!";  fi $ cp -f $(BOARD_DIR)/include/rcS.template $/rcS.template $ tools/mkromfsimg.sh $ $ if [ ! -f $/nsh_romfsimg.h ]; then  echo "No nsh_romfsimg.h file create !!!!!";  fi $ cp -f nsh_romfsimg.h arch/arm/include/board/ $ rm -f $/rcS.template $/nsh_romfsimg.helse $ echo "use nsh defalut nsh_romfsimg.h for romfs"endif# Targets used to build include/nuttx/config.h. Creation of config.h is# part of the overall NuttX configuration sequence. Notice that the# tools/mkconfig tool is built and used to create include/nuttx/config.h# 创建config.h文件tools/mkconfig$(HOSTEXEEXT): $ $ -C tools -f Makefile.host TOPDIR="$" mkconfig$(HOSTEXEEXT)include/nuttx/config.h: $/.config tools/mkconfig$(HOSTEXEEXT) $ tools/mkconfig $ > include/nuttx/config.h# Targets used to create dependencies# 编译Host上创建dependency的工具tools/mkdeps$(HOSTEXEEXT): $ $ -C tools -f Makefile.host TOPDIR="$" mkdeps$(HOSTEXEEXT)tools/cnvwindeps$(HOSTEXEEXT): $ $ -C tools -f Makefile.host TOPDIR="$" cnvwindeps$(HOSTEXEEXT)# dirlinks, and helpers## Directories links. Most of establishing the NuttX configuration involves# setting up symbolic links with 'generic' directory names to specific,# configured directories.# Make.defs:# $ echo "No Make.defs file found, creating one"# $ echo "include $$.config" > Make.defs# $ echo "include $$tools$Config.mk" >> Make.defs# tools/initialconfig$(HOSTEXEEXT):# $ $ -C tools -f Makefile.host TOPDIR="$" initialconfig$(HOSTEXEEXT)## .config: tools/initialconfig$(HOSTEXEEXT)# $ echo "No .config file found, creating one"# $ tools/initialconfig$(HOSTEXEEXT)# Link the arch/<arch-name>/include directory to include/archinclude/arch: .config @echo "LN: include/arch to $/include" $ $ $/$/include include/arch# Link the configs/<board-name>/include directory to include/arch/boardinclude/arch/board: include/arch @echo "LN: include/arch/board to $(BOARD_DIR)/include" $ $ $(BOARD_DIR)/include include/arch/board# Link the configs/<board-name>/src dir to arch/<arch-name>/src/board$/board: .config @echo "LN: $/board to $(BOARD_DIR)/src" $ $ $(BOARD_DIR)/src $/board# Link arch/<arch-name>/include/<chip-name> to arch/<arch-name>/include/chip$/chip: .configifneq ($(CONFIG_ARCH_CHIP),) @echo "LN: $/chip to $/$(CONFIG_ARCH_CHIP)" $ $ $/$/$(CONFIG_ARCH_CHIP) $/chipendif# Link arch/<arch-name>/src/<chip-name> to arch/<arch-name>/src/chipinclude/arch/chip: include/archifneq ($(CONFIG_ARCH_CHIP),) @echo "LN: include/arch/chip to $/$(CONFIG_ARCH_CHIP)" $ $ $/$/$(CONFIG_ARCH_CHIP) include/arch/chipendif# 根据依赖关系创建链接,进入nuttx/configs目录中,执行make dirlinks;进入apps/目录中,执行make dirlinksdirlinks: include/arch include/arch/board include/arch/chip $/board $/chip $ $ -C configs dirlinks TOPDIR="$" $ $ -C $(CONFIG_APPS_DIR) dirlinks TOPDIR="$"# context## The context target is invoked on each target build to assure that NuttX is# properly configured. The basic configuration steps include creation of the# the config.h and version.h header files in the include/nuttx directory and# the establishment of symbolic links to configured directories.# CONTEXTDIRS在Directories.mk中定义context: check_context include/nuttx/config.h include/nuttx/version.h include/math.h include/float.h include/stdarg.h dirlinks arch/arm/include/board/nsh_romfsimg.h $ for dir in $(CONTEXTDIRS) ; do  $ -C $$dir TOPDIR="$" context;  done# clean_context## This is part of the distclean target. It removes all of the header files# and symbolic links created by the context target.clean_context: $ $ -C configs TOPDIR="$" clean_context $(call DELFILE, include/nuttx/config.h) $(call DELFILE, include/nuttx/version.h) $(call DELFILE, arch/arm/include/board/nsh_romfsimg.h) $(call DELFILE, include/math.h) $(call DELFILE, include/stdarg.h) $ $(DIRUNLINK) include/arch/board $ $(DIRUNLINK) include/arch/chip $ $(DIRUNLINK) include/arch $ $(DIRUNLINK) $/board $ $(DIRUNLINK) $/chip# 检查Nuttx是否已经被配置好# check_context## This target checks if NuttX has been configured. NuttX is configured using# the script tools/configure.sh. That script will install certain files in# the top-level NuttX build directory. This target verifies that those# configuration files have been installed and that NuttX is ready to be built.check_context: $ if [ ! -e ${TOPDIR}/.config -o ! -e ${TOPDIR}/Make.defs ]; then  echo "" ; echo "Nuttx has not been configured:" ;  echo " cd tools; ./configure.sh <target>" ; echo "" ;  exit 1 ;  fi# Archive targets. The target build sequence will first create a series of# libraries, one per configured source file directory. The final NuttX# execution will then be built from those libraries. The following targets# build those libraries.#包含各种库文件include LibTargets.mk# pass1 and pass2## If the 2 pass build option is selected, then this pass1 target is# configured to built before the pass2 target. This pass1 target may, as an# example, build an extra link object (CONFIG_PASS1_OBJECT) which may be an# incremental  link object, but could be a static library ;# some modification to this Makefile would be required if CONFIG_PASS1_OBJECT# is an archive. Exactly what is performed during pass1 or what it generates# is unknown to this makefile unless CONFIG_PASS1_OBJECT is defined.# PASS1为apps部分pass1deps: pass1dep $# 如果定义了CONFIG_BUILD_2PASS,则需要先编译PASS1pass1: pass1depsifeq ($(CONFIG_BUILD_2PASS),y) $ if [ -z "$(CONFIG_PASS1_BUILDIR)" ]; then  echo "ERROR: CONFIG_PASS1_BUILDIR not defined";  exit 1;  fi $ if [ ! -d "$(CONFIG_PASS1_BUILDIR)" ]; then  echo "ERROR: CONFIG_PASS1_BUILDIR does not exist";  exit 1;  fi $ if [ ! -f "$(CONFIG_PASS1_BUILDIR)/Makefile" ]; then  echo "ERROR: No Makefile in CONFIG_PASS1_BUILDIR";  exit 1;  fi $ $ -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$" LINKLIBS="$" USERLIBS="$" "$(CONFIG_PASS1_TARGET)"endif# PASS2为nuttx部分pass2deps: pass2dep $(NUTTXLIBS)pass2: pass2deps $ $ -C $ TOPDIR="$" EXTRA_OBJS="$(EXTRA_OBJS)" LINKLIBS="$" EXTRADEFINES=$ $ if [ -w /tftpboot ] ; then  cp -f $ /tftpboot/$.${CONFIG_ARCH};  fiifeq ($(CONFIG_RRLOAD_BINARY),y) @echo "MK: $(NUTTXNAME).rr" $ $/tools/mkimage.sh --Prefix $ $ $(NUTTXNAME).rr $ if [ -w /tftpboot ] ; then  cp -f $(NUTTXNAME).rr /tftpboot/$(NUTTXNAME).rr.$(CONFIG_ARCH);  fiendififeq ($(CONFIG_INTELHEX_BINARY),y) @echo "CP: $(NUTTXNAME).hex" $ $ $(OBJCOPYARGS) -O ihex $ $(NUTTXNAME).hexendififeq ($(CONFIG_MOTOROLA_SREC),y) @echo "CP: $(NUTTXNAME).srec" $ $ $(OBJCOPYARGS) -O srec $ $(NUTTXNAME).srecendififeq ($(CONFIG_RAW_BINARY),y) #生成RAW格式文件,并生成nuttx.bin文件 @echo "CP: $(NUTTXNAME).bin" $ $ $(OBJCOPYARGS) -O binary $ $(NUTTXNAME).binendififeq ($(CONFIG_UBOOT_UIMAGE),y) @echo "MKIMAGE: uImage" $ mkimage -A arm -O linux -C none -T kernel -a $(CONFIG_UIMAGE_LOAD_ADDRESS)  -e $(CONFIG_UIMAGE_ENTRY_POINT) -n $ -d $(NUTTXNAME).bin uImage $ if [ -w /tftpboot ] ; then  cp -f uImage /tftpboot/uImage;  fiendif# $## Create the final NuttX executable in a two pass build process. In the# normal case, all pass1 and pass2 dependencies are created then pass1# and pass2 targets are built. However, in some cases, you may need to build# pass1 dependencies and pass1 first, then build pass2 dependencies and pass2.# in that case, execute 'make pass1 pass2' from the command line.$: pass1deps pass2deps pass1 pass2# download## This is a helper target that will rebuild NuttX and download it to the target# system in one step. The operation of this target depends completely upon# implementation of the DOWNLOAD command in the user Make.defs file. It will# generate an error an error if the DOWNLOAD command is not defined.download: $ $(call DOWNLOAD, $<)# pass1dep: Create pass1 build dependencies# pass2dep: Create pass2 build dependencies# 创建pass1的依赖关系,make depend后,将会生成Make.dep文件pass1dep: context tools/mkdeps$(HOSTEXEEXT) tools/cnvwindeps$(HOSTEXEEXT) $ for dir in $(USERDEPDIRS) ; do  $ -C $$dir TOPDIR="$" depend ;  done# 创建pass2的依赖关系,make depend后,将会生成Make.dep文件pass2dep: context tools/mkdeps$(HOSTEXEEXT) tools/cnvwindeps$(HOSTEXEEXT) $ for dir in $(KERNDEPDIRS) ; do  $ -C $$dir TOPDIR="$" EXTRADEFINES=$ depend;  done# Configuration targets## These targets depend on the kconfig-frontends packages. To use these, you# must first download and install the kconfig-frontends package from this# location: http://ymorin.is-a-geek.org/projects/kconfig-frontends. See# README.txt file in the NuttX tools GIT repository for additional information.# 配置目标do_config: dirlinks apps_preconfig $ APPSDIR=${CONFIG_APPS_DIR} kconfig-conf Kconfigconfig: do_config clean_contextdo_oldconfig: dirlinks apps_preconfig $ APPSDIR=${CONFIG_APPS_DIR} kconfig-conf --oldconfig Kconfigoldconfig: do_oldconfig clean_contextdo_olddefconfig: dirlinks apps_preconfig $ APPSDIR=${CONFIG_APPS_DIR} kconfig-conf --olddefconfig Kconfigolddefconfig: do_olddefconfig clean_contextdo_menuconfig: dirlinks apps_preconfig $ APPSDIR=${CONFIG_APPS_DIR} kconfig-mconf Kconfigmenuconfig: do_menuconfig clean_contextdo_qconfig: dirlinks apps_preconfig $ APPSDIR=${CONFIG_APPS_DIR} kconfig-qconf Kconfigqconfig: do_qconfig clean_contextdo_gconfig: dirlinks apps_preconfig $ APPSDIR=${CONFIG_APPS_DIR} kconfig-gconf Kconfiggconfig: do_gconfig clean_context# export## The export target will package the NuttX libraries and header files into# an exportable package. Caveats:  These needs some extension for the KERNEL# build; it needs to receive USERLIBS and create a libuser.a).  The logic# in tools/mkexport.sh only supports GCC and, for example, explicitly assumes# that the archiver is 'ar'# 'make export'将生成一个打包文件,将nuttx内核中的库及头文件放置在一起export: pass2deps $ MAKE=${MAKE} $ $(MKEXPORT_ARGS) -l "$(EXPORTLIBS)"# General housekeeping targets: dependencies, cleaning, etc.## depend: Create both PASS1 and PASS2 dependencies# clean: Removes derived object files, archives, executables, and# temporary files, but retains the configuration and context# files and directories.# distclean: Does 'clean' then also removes all configuration and context# files. This essentially restores the directory structure# to its original, unconfigured stated.# 生成依赖关系depend: pass1dep pass2depsubdir_clean: $ for dir in $(CLEANDIRS) ; do  if [ -e $$dir/Makefile ]; then  $ -C $$dir TOPDIR="$" clean ;  fi  done $ $ -C tools -f Makefile.host TOPDIR="$" cleanifeq ($(CONFIG_BUILD_2PASS),y) $ $ -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$" cleanendif# make clean,将目录中生成的文件都删除掉clean: subdir_clean $(call DELFILE, $ $(call DELFILE, nuttx.*) $(call DELFILE, *.map) $(call DELFILE, _SAVED_APPS_config) $(call DELFILE, nuttx-export*) $(call DELFILE, nuttx_user*) $(call CLEAN)subdir_distclean: $ for dir in $(CLEANDIRS) ; do  if [ -e $$dir/Makefile ]; then  $ -C $$dir TOPDIR="$" distclean ;  fi  done# make distclean,将目录中生成的文件,以及配置项都删除掉distclean: clean subdir_distclean clean_contextifeq ($(CONFIG_BUILD_2PASS),y) $ $ -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$" distcleanendif $(call DELFILE, Make.defs) $(call DELFILE, .config) $(call DELFILE, .config.old)# Application housekeeping targets. The APPDIR variable refers to the user# application directory. A sample apps/ directory is included with NuttX,# however, this is not treated as part of NuttX and may be replaced with a# different application directory. For the most part, the application# directory is treated like any other build directory in this script. However,# as a convenience, the following targets are included to support housekeeping# functions in the user application directory from the NuttX build directory.## apps_preconfig: Prepare applications to be configured# apps_clean: Perform the clean operation only in the user application# directory# apps_distclean: Perform the distclean operation only in the user application# directory.# 针对apps目录下的配置及清除工作apps_preconfig:ifneq ,) $ $ -C "$/$" TOPDIR="$" preconfigendifapps_clean:ifneq ,) $ $ -C "$/$" TOPDIR="$" cleanendifapps_distclean:ifneq ,) $ $ -C "$/$" TOPDIR="$" distcleanendif

假设yusen@Foxmail.com出殡一封邮件到yusen@yusengy.info中.

Nuttx相关的历史篇章:

  • Nuttx Task Schedule
  • Nuttx复信号机制
  • Nuttx编写翻译系统
  • Nuttx信息队列机制
  • Nuttx专业行列机制

  • 信号量

  1. 获得实践时候的连串时间,这一个时刻首要用来计算职责步向专门的学问行列后,消耗了多短时间,是或不是到了急需去执行的时间点。
  2. 从办事行列的头顶获取一个职分,通过相比四个时刻值:1)消耗的时间,也正是方今的系统时间减去职分入列的时日;2)职分延迟执行的时日,也正是数据结构中叙述的delay时间。
  3. 即便消耗的年华高出延迟推行的大运,那就应声推行任务的回调函数。
  4. 要是消耗的日子低于延迟实践的日子,总括剩余时间,并最终让职务睡眠等待一下。5.高优先级内核工作行列和低优先内核专门的学业行列的贯彻格局有点微小的差距,首要反映在,高优先级的事态下,假诺还不到施行时间,专业线程选拔睡眠让出CPU;低优先级的状态下,会挑选让第一个线程轮询(与高优先级工作线程行为无差异于),而让别的的行事线程调用sigwaitinfo()接口等待信号。代码如下:
/**************************************************************************** * Name: mq_receive * * Description: * This function receives the oldest of the highest priority messages * from the message queue specified by "mqdes." If the size of the * buffer in bytes  is less than the "mq_msgsize" attribute of * the message queue, mq_receive will return an error. Otherwise, the * selected message is removed from the queue and copied to "msg." * * If the message queue is empty and O_NONBLOCK was not set, * mq_receive() will block until a message is added to the message * queue. If more than one task is waiting to receive a message, only * the task with the highest priority that has waited the longest will * be unblocked. * * If the queue is empty and O_NONBLOCK is set, ERROR will be returned. * * Parameters: * mqdes - Message Queue Descriptor * msg - Buffer to receive the message * msglen - Size of the buffer in bytes * prio - If not NULL, the location to store message priority. * * Return Value: * One success, the length of the selected message in bytes is returned. * On failure, -1  is returned and the errno is set appropriately: * * EAGAIN The queue was empty, and the O_NONBLOCK flag was set * for the message queue description referred to by 'mqdes'. * EPERM Message queue opened not opened for reading. * EMSGSIZE 'msglen' was less than the maxmsgsize attribute of the * message queue. * EINTR The call was interrupted by a signal handler. * EINVAL Invalid 'msg' or 'mqdes' * * Assumptions: * ****************************************************************************/ssize_t mq_receive(mqd_t mqdes, FAR char *msg, size_t msglen, FAR int *prio){ FAR struct mqueue_msg_s *mqmsg; irqstate_t flags; ssize_t ret = ERROR; DEBUGASSERT(up_interrupt_context() == false); /* mq_receive() is a cancellation point */ enter_cancellation_point(); /* Verify the input parameters and, in case of an error, set * errno appropriately. */ if (mq_verifyreceive(mqdes, msg, msglen) != OK) { leave_cancellation_point(); return ERROR; } /* Get the next message from the message queue. We will disable * pre-emption until we have completed the message received. This * is not too bad because if the receipt takes a long time, it will * be because we are blocked waiting for a message and pre-emption * will be re-enabled while we are blocked */ sched_lock(); /* Furthermore, mq_waitreceive() expects to have interrupts disabled * because messages can be sent from interrupt level. */ flags = enter_critical_section(); /* Get the message from the message queue */ mqmsg = mq_waitreceive; leave_critical_section; /* Check if we got a message from the message queue. We might * not have a message if: * * - The message queue is empty and O_NONBLOCK is set in the mqdes * - The wait was interrupted by a signal */ if  { ret = mq_doreceive(mqdes, mqmsg, msg, prio); } sched_unlock(); leave_cancellation_point(); return ret;}

/**************************************************************************** * Name: mq_waitreceive * * Description: * This is internal, common logic shared by both mq_receive and * mq_timedreceive. This function waits for a message to be received on * the specified message queue, removes the message from the queue, and * returns it. * * Parameters: * mqdes - Message queue descriptor * * Return Value: * On success, a reference to the received message. If the wait was * interrupted by a signal or a timeout, then the errno will be set * appropriately and NULL will be returned. * * Assumptions: * - The caller has provided all validity checking of the input parameters * using mq_verifyreceive. * - Interrupts should be disabled throughout this call. This is necessary * because messages can be sent from interrupt level processing. * - For mq_timedreceive, setting of the timer and this wait must be atomic. * ****************************************************************************/FAR struct mqueue_msg_s *mq_waitreceive(mqd_t mqdes){ FAR struct tcb_s *rtcb; FAR struct mqueue_inode_s *msgq; FAR struct mqueue_msg_s *rcvmsg; /* mq_waitreceive() is not a cancellation point, but it is always called * from a cancellation point. */ if (enter_cancellation_point {#ifdef CONFIG_CANCELLATION_POINTS /* If there is a pending cancellation, then do not perform * the wait. Exit now with ECANCELED. */ set_errno(ECANCELED); leave_cancellation_point(); return NULL;#endif } /* Get a pointer to the message queue */ msgq = mqdes->msgq; /* Get the message from the head of the queue */ while ((rcvmsg = (FAR struct mqueue_msg_s *)sq_remfirst(&msgq->msglist)) == NULL) { /* The queue is empty! Should we block until there the above condition * has been satisfied? */ if ((mqdes->oflags & O_NONBLOCK) == 0) { /* Yes.. Block and try again */ rtcb = this_task(); rtcb->msgwaitq = msgq; msgq->nwaitnotempty++; set_errno; up_block_task(rtcb, TSTATE_WAIT_MQNOTEMPTY); /* When we resume at this point, either  the message queue * is no longer empty, or  the wait has been interrupted by * a signal. We can detect the latter case be examining the * errno value (should be either EINTR or ETIMEDOUT). */ if (get_errno { break; } } else { /* The queue was empty, and the O_NONBLOCK flag was set for the * message queue description referred to by 'mqdes'. */ set_errno; break; } } /* If we got message, then decrement the number of messages in * the queue while we are still in the critical section */ if  { msgq->nmsgs--; } leave_cancellation_point(); return rcvmsg;}

/**************************************************************************** * Name: mq_doreceive * * Description: * This is internal, common logic shared by both mq_receive and * mq_timedreceive. This function accepts the message obtained by * mq_waitmsg, provides the message content to the user, notifies any * threads that were waiting for the message queue to become non-full, * and disposes of the message structure * * Parameters: * mqdes - Message queue descriptor * mqmsg - The message obtained by mq_waitmsg() * ubuffer - The address of the user provided buffer to receive the message * prio - The user-provided location to return the message priority. * * Return Value: * Returns the length of the received message. This function does not fail. * * Assumptions: * - The caller has provided all validity checking of the input parameters * using mq_verifyreceive. * - The user buffer, ubuffer, is known to be large enough to accept the * largest message that an be sent on this message queue * - Pre-emption should be disabled throughout this call. * ****************************************************************************/ssize_t mq_doreceive(mqd_t mqdes, FAR struct mqueue_msg_s *mqmsg, FAR char *ubuffer, int *prio){ FAR struct tcb_s *btcb; irqstate_t flags; FAR struct mqueue_inode_s *msgq; ssize_t rcvmsglen; /* Get the length of the message (also the return value) */ rcvmsglen = mqmsg->msglen; /* Copy the message into the caller's buffer */ memcpy(ubuffer, (FAR const void *)mqmsg->mail, rcvmsglen); /* Copy the message priority as well (if a buffer is provided) */ if  { *prio = mqmsg->priority; } /* We are done with the message. Deallocate it now. */ mq_msgfree; /* Check if any tasks are waiting for the MQ not full event. */ msgq = mqdes->msgq; if (msgq->nwaitnotfull > 0) { /* Find the highest priority task that is waiting for * this queue to be not-full in g_waitingformqnotfull list. * This must be performed in a critical section because * messages can be sent from interrupt handlers. */ flags = enter_critical_section(); for (btcb = (FAR struct tcb_s *)g_waitingformqnotfull.head; btcb && btcb->msgwaitq != msgq; btcb = btcb->flink); /* If one was found, unblock it. NOTE: There is a race * condition here: the queue might be full again by the * time the task is unblocked */ ASSERT; btcb->msgwaitq = NULL; msgq->nwaitnotfull--; up_unblock_task; leave_critical_section; } /* Return the length of the message transferred to the user buffer */ return rcvmsglen;}

Make.defs中定义了某个板级相关的宏定义。

  1. MUA请求Postfix建立SMTP连接
  2. Postfix发送SSL证书给MUA
  3. MUA发送账号密码给Postfix,央求验证
  4. Postfix央求Dovecot验证账号密码.
  5. Dovecot必要MySQL查询结果
  6. MySQL再次来到查询结果.
  7. Dovecot重返Postfix账号密码验证结果.
  8. Postfix重返MUA账号密码验证结果.
  9. MUA使用SMTP公约发送邮件到Postfix.
  10. Postfix把邮件实行发送.接下去的步调参考前边服务器查收邮件的进程.

或许从几个重大的函数来剖判吧:

work_process()产生的机要职分有:

/**************************************************************************** * Name: mq_open * * Description: * This function establish a connection between a named message queue and * the calling task. After a successful call of mq_open(), the task can * reference the message queue using the address returned by the call. The * message queue remains usable until it is closed by a successful call to * mq_close(). * * Parameters: * mq_name - Name of the queue to open * oflags - open flags * Optional parameters. When the O_CREAT flag is specified, two optional * parameters are expected: * * 1. mode_t mode , and * 2. struct mq_attr *attr. The mq_maxmsg attribute * is used at the time that the message queue is * created to determine the maximum number of * messages that may be placed in the message queue. * * Return Value: * A message queue descriptor or -1  * * Assumptions: * ****************************************************************************/mqd_t mq_open(FAR const char *mq_name, int oflags, ...){... sched_lock(); /* Get the inode for this mqueue. This should succeed if the message * queue has already been created. In this case, inode_find() will * have incremented the reference count on the inode. */ SETUP_SEARCH(&desc, fullpath, false); ret = inode_find(&desc); if (ret >= 0) { /* Something exists at this path. Get the search results */ inode = desc.node; DEBUGASSERT(inode != NULL); /* Verify that the inode is a message queue */ if (!INODE_IS_MQUEUE { errcode = ENXIO; goto errout_with_inode; } /* It exists and is a message queue. Check if the caller wanted to * create a new mqueue with this name. */ if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { errcode = EEXIST; goto errout_with_inode; } /* Create a message queue descriptor for the current thread */ msgq = inode->u.i_mqueue; mqdes = mq_descreate(NULL, msgq, oflags); if  { errcode = ENOMEM; goto errout_with_inode; } } else { /* The mqueue does not exists. Were we asked to create it? */ if ((oflags & O_CREAT) == 0) { /* The mqueue does not exist and O_CREAT is not set */ errcode = ENOENT; goto errout_with_lock; } /* Create the mqueue. First we have to extract the additional * parameters from the variable argument list. */ va_start(ap, oflags); mode = va_arg(ap, mode_t); attr = va_arg(ap, FAR struct mq_attr *); va_end; /* Create an inode in the pseudo-filesystem at this path */ inode_semtake(); ret = inode_reserve(fullpath, &inode); inode_semgive(); if (ret < 0) { errcode = -ret; goto errout_with_lock; } /* Allocate memory for the new message queue. The new inode will * be created with a reference count of zero. */ msgq = (FAR struct mqueue_inode_s *)mq_msgqalloc(mode, attr); if  { errcode = ENOSPC; goto errout_with_inode; } /* Create a message queue descriptor for the TCB */ mqdes = mq_descreate(NULL, msgq, oflags); if  { errcode = ENOMEM; goto errout_with_msgq; } /* Bind the message queue and the inode structure */ INODE_SET_MQUEUE; inode->u.i_mqueue = msgq; msgq->inode = inode; /* Set the initial reference count on this inode to one */ inode->i_crefs = 1; } RELEASE_SEARCH(&desc); sched_unlock();...}

内存配置在Flat情势情形下,会动用FlatLibs.mk文件,该文件重大定义NUTTXLIBSUSERLIBS,其中NUTTXLIBS蕴涵了一体系的库文件,最后用于特定管理器来编写翻译Nuttx ImageUSERLIBS含有一层层库文件用于客商层的Apps。别的,还定义了EXPORTLIBS,用于在make export时,生成库文件。

DKIM:DomainKeys Identified Mail.功效指标与SPF相似,首如果让收件人能够透过加密解密的艺术来获知发件人是不是是真实的.原理正是在电子邮件的上马插入一段签字,然后接收方通过从DNS查询获得公钥以往,以拓宽求证,与SSH的公钥和密钥类似.记录日常如下:

/**************************************************************************** * Name: sem_wait * * Description: * This function attempts to lock the semaphore referenced by 'sem'. If * the semaphore value is  zero, then the calling task will not return * until it successfully acquires the lock. * * Parameters: * sem - Semaphore descriptor. * * Return Value: * 0 , or -1  is unsuccessful * If this function returns -1 , then the cause of the failure will * be reported in 'errno' as: * - EINVAL: Invalid attempt to get the semaphore * - EINTR: The wait was interrupted by the receipt of a signal. * * Assumptions: * ****************************************************************************/int sem_wait(FAR sem_t *sem){ FAR struct tcb_s *rtcb = this_task(); irqstate_t flags; int ret = ERROR; /* This API should not be called from interrupt handlers */ DEBUGASSERT(sem != NULL && up_interrupt_context() == false); /* The following operations must be performed with interrupts * disabled because sem_post() may be called from an interrupt * handler. */ flags = enter_critical_section(); /* sem_wait() is a cancellation point */ if (enter_cancellation_point {#ifdef CONFIG_CANCELLATION_POINTS /* If there is a pending cancellation, then do not perform * the wait. Exit now with ECANCELED. */ set_errno(ECANCELED); leave_cancellation_point(); leave_critical_section; return ERROR;#endif } /* Make sure we were supplied with a valid semaphore. */ if (sem != NULL) { /* Check if the lock is available */ if (sem->semcount > 0) { /* It is, let the task take the semaphore. */ sem->semcount--; sem_addholder; rtcb->waitsem = NULL; ret = OK; } /* The semaphore is NOT available, We will have to block the * current thread of execution. */ else { /* First, verify that the task is not already waiting on a * semaphore */ ASSERT(rtcb->waitsem == NULL); /* Handle the POSIX semaphore (but don't set the owner yet) */ sem->semcount--; /* Save the waited on semaphore in the TCB */ rtcb->waitsem = sem; /* If priority inheritance is enabled, then check the priority of * the holder of the semaphore. */#ifdef CONFIG_PRIORITY_INHERITANCE /* Disable context switching. The following operations must be * atomic with regard to the scheduler. */ sched_lock(); /* Boost the priority of any threads holding a count on the * semaphore. */ sem_boostpriority;#endif /* Add the TCB to the prioritized semaphore wait queue */ set_errno; up_block_task(rtcb, TSTATE_WAIT_SEM); /* When we resume at this point, either  the semaphore has been * assigned to this thread of execution, or  the semaphore wait * has been interrupted by a signal or a timeout. We can detect these * latter cases be examining the errno value. * * In the event that the semaphore wait was interrupted by a signal or * a timeout, certain semaphore clean-up operations have already been * performed (see sem_waitirq.c). Specifically: * * - sem_canceled() was called to restore the priority of all threads * that hold a reference to the semaphore, * - The semaphore count was decremented, and * - tcb->waitsem was nullifed. * * It is necesaary to do these things in sem_waitirq.c because a long * time may elapse between the time that the signal was issued and * this thread is awakened and this leaves a door open to several * race conditions. */ if (get_errno() != EINTR && get_errno() != ETIMEDOUT) { /* Not awakened by a signal or a timeout... * * NOTE that in this case sem_addholder() was called by logic * in sem_wait() fore this thread was restarted. */ ret = OK; }#ifdef CONFIG_PRIORITY_INHERITANCE sched_unlock();#endif } } else { set_errno; } leave_cancellation_point(); leave_critical_section; return ret;}

struct work_s结构只要求用来声称实例就能够,该数据结构中的内部成员,全体由相应的API接口来操作,当中qtime意味着的是该任务入队的小时,而delay意味着的是需求延期多久去实行,假如delay值为0,证明立时施行。

该组织主要陈述消息的分红项目、优先级、新闻的长度,以及音信的剧情。

# NUTTXLIBS is the list of NuttX libraries that is passed to the# processor-specific Makefile to build the final NuttX target.# Libraries in FSDIRS are excluded if file descriptor support# is disabled.# USERLIBS is the list of libraries used to build the final user-space# application# EXPORTLIBS is the list of libraries that should be exported by# 'make export' isNUTTXLIBS = lib$libsched$USERLIBS =# Driver support. Generally depends on file descriptor support but there# are some components in the drivers directory that are needed even if file# descriptors are not supported.NUTTXLIBS += lib$libdrivers$# Add libraries for board supportNUTTXLIBS += lib$libconfigs$# Add libraries for syscall support.NUTTXLIBS += lib$libc$ lib$libmm$NUTTXLIBS += lib$libarch$ifeq ($(CONFIG_LIB_SYSCALL),y)NUTTXLIBS += lib$libstubs$USERLIBS += lib$libproxies$endif# Add libraries for C++ support. CXX, CXXFLAGS, and COMPILEXX must# be defined in Make.defs for this to work!ifeq ($(CONFIG_HAVE_CXX),y)NUTTXLIBS += lib$libcxx$endif# Add library for application support.ifneq ,)NUTTXLIBS += lib$libapps$endif# Add libraries for network supportifeq ($(CONFIG_NET),y)NUTTXLIBS += lib$libnet$endif# Add libraries for Crypto API supportifeq ($(CONFIG_CRYPTO),y)NUTTXLIBS += lib$libcrypto$endif# Add libraries for file system supportifeq ($(CONFIG_NFILE_DESCRIPTORS),0)ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0)NUTTXLIBS += lib$libfs$endifelseNUTTXLIBS += lib$libfs$ lib$libbinfmt$endif# Add libraries for the NX graphics sub-systemifeq ($(CONFIG_NX),y)NUTTXLIBS += lib$libgraphics$NUTTXLIBS += lib$libnx$endif# Add libraries for the Audio sub-systemifeq ($(CONFIG_AUDIO),y)NUTTXLIBS += lib$libaudio$endif# Add libraries for the Wireless sub-systemifeq ($(CONFIG_WIRELESS),y)NUTTXLIBS += lib$libwireless$endif# Add C++ libraryifeq ($(CONFIG_HAVE_CXX),y)NUTTXLIBS += lib$libcxx$endif# Export all librariesEXPORTLIBS = $(NUTTXLIBS)

创制虚构邮箱配置

创建: /etc/postfix/mysql-virtual_mailboxes.cf

user = mail_adminpassword = mys123123dbname = mailquery = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM users WHERE email='%s'hosts = 127.0.0.1
  • Locking信号量 VS Signaling信号量
  • 职责队列:用于存放须求延期实施的任务,这一个也正是通过work_queue()接口加多职分的职责队列。
  • 干活线程:在高优先级内核工作行列中,私下认可独有一个线程;在低优先级内核专门的学问行列中协理七个专门的工作线程。职责队列中的任务就分发到那些线程上来实践。
  • 延时参数delay:那个参数定义了轮询时的间隔时间,进而决断职责队列中的职分是不是已经到要求实行的小时点了。
/* The g_msgfree is a list of messages that are available for general use. * The number of messages in this list is a system configuration item. */EXTERN sq_queue_t g_msgfree;/* The g_msgfreeInt is a list of messages that are reserved for use by * interrupt handlers. */EXTERN sq_queue_t g_msgfreeirq;/* The g_desfree data structure is a list of message descriptors available * to the operating system for general use. The number of messages in the * pool is a constant. */EXTERN sq_queue_t g_desfree;

Directories.mk主要定义了NUTTX_ADDONSUSER_ADDONS,其中NUTTX_ADDONS含蓄了一文山会海文件夹,最后将编写翻译进Nuttx内核中,而USER_ADDONS包含了一层层文件夹,最终会编写翻译进Apps中。Directories.mk将Nuttx内核中的文件夹都包括了进来。

  1. foxmail.com服务器会透过DNS查询到yusengy.info的MX记录,然后找到Postfix所在的服务器所在.
  2. 邮件通过SMTP合同发送给Postfix.
  3. Postfix通过MySQL查询,yusengy.info是不是是本机需求处理的域名.
  4. MySQL通过查询再次回到确认音讯给Postfix.
  5. Nuttx消息队列机制,从零开首邮件服务器搭建。Postfix拿到承认音讯,把邮件传送给Dovecot,由Dovecot的LMTP服务以来投递专门的学问.
  6. Dovecot把邮件的故事情节保存在对应的门路中.

重在的数据结构分为两有的:

  • 高优先级内核工作行列专项使用的高优先级工作行列用于中断管理函数中的延迟管理,在多少驱动中恐怕必要如此三个职业行列,如果不供给的话,也得以安枕而卧的禁掉。高优先级的线程也足以充任能源回收器--从当中断管理函数中成就内部存款和储蓄器的推移释放。假设高优先级职业线程被disable了的话,清理专门的学业有三种办法来成功:1)借使使能了低优先级的劳作线程,在该线程中做到;2)假诺低优先级线程未有使能,则IDLE线程来造成(即使内部存款和储蓄器回收优先级相比高,可能不太相符)。

  • 设备驱动底半部高优先级职业线程能够用来器材驱动程序的底半部,因而它必需运转在叁个不胜高,并且定位的优先级,与中断管理程序本人的预先级竞争。平日,高优先级工作行列应该是系统中最高优先级的线程。暗中认可的优先级为224。

  • 线程池专门的工作行列能够被布置成援助两个低优先级线程,那精神上是二个线程池,为队列工作提供多线程服务,那打破了“队列”的严刻种类化(由此,职业行列也不再是一种队列)。当在I/O操作,暂停等待输入时,四个干活线程是索要的,要是只有二个行事线程的话,那么整个办事行列管理就能告一段落。那对于异步I/O、AIO是少不了的。

  • 与低优先级内核专门的职业行列相比对于不太主要、非常低优先级、面向应用程序的办事线程辅助,怀恋使用异常低优先级的劳作行列。比较低优先级的干活行列以异常的低的事先级运转,可是它有两个外加的帮助和益处,那正是支撑优先级承接(假诺CONFIG_PRIORITY_INHERITANCE=y入选的话):低优先级的干活线程能够被调度优先级。

  • 布局选项CONFIG_SCHED_HPWORK:使能高优先级专门的工作行列CONFIG_SCHED_HPNTHREADS:高优先级职业队列线程池中的线程数量,暗中认可是1.CONFIG_SCHED_HPWORKPRIORITY:高优先级工作线程的试行优先级,暗中认可是224.CONFIG_SCHED_HPWORKSTACKSIZE:工作线程的栈空间大小,默许是2048字节

  • 通用配置选项那个选项通用于全部的劳作行列:CONFIG_SIG_SIGWORK:用于唤醒职业线程的数字信号值,私下认可使用17.

别的,还或许有多个全局的队列,当中g_msgfreeg_msgfreeirq队列用于存放message,差别是是或不是在脚刹踏板管理函数中去行使。message会从那七个系列中举办申请,出席到新闻队列中,当最后成功了新闻的传递后,会将message再增加到那多少个类别中。g_desfree队列用于贮存音讯队列描述符,每贰个音信队列都对应二个描述符,当音信队列销毁的时候,供给将音信队列描述符增添到g_desfree队列中。

...-include .config #将.config文件包含进来,其中`-`表示如果.config文件不存在,Makefile也不会报错,并继续运行ifeq ($(CONFIG_WINDOWS_NATIVE),y)include Makefile.winelseinclude Makefile.unix #根据编译环境,选择对应的Makefile,真正的入口endif

数据库大概浏览

创建mail数据库用以管理邮件相关的业务.并且创办邮件管理员.

GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mail_admin'@'localhost' IDENTIFIED BY 'mys123123';GRANT SELECT, INSERT, UPDATE, DELETE ON mail.* TO 'mail_admin'@'localhost.localdomain' IDENTIFIED BY 'mys123123';FLUSH PRIVILEGES;

这里的mys123123替换来本身的密码.作者那边只是做示范应用,实际中应有运用强度更加大的字符串作为密码.

图片 1数据库mail数据库中一齐有4个表,分别是虚拟域名, 邮件转发, 用户信息以及传输路径四个表..图片 2表格

该表存款和储蓄的是本土服务器用来接受邮件的域名.

图片 3设想域名表表结构

成立语句

CREATE TABLE domains (domain varchar NOT NULL, PRIMARY KEY ;

可以用来转载邮件.

图片 4邮件发送表表结构

CREATE TABLE forwardings (source varchar NOT NULL, destination TEXT NOT NULL, PRIMARY KEY ;

用来存款和储蓄客户的账号密码.这里密码使用加密的方法开展存款和储蓄.

图片 5客户消息表结构

CREATE TABLE users (email varchar NOT NULL, password varchar NOT NULL, PRIMARY KEY ;

传输表能够用来指定邮件的传导路线.

图片 6传输表结构

CREATE TABLE transport ( domain varchar NOT NULL default '', transport varchar NOT NULL default '', UNIQUE KEY domain ;

在配备完数据库现在,大家最佳修改数据库的布置文件,只同意地点访问数据库,进步安全性.修改: /etc/my.cnf

bind-address=127.0.0.1

只要数据库存款和储蓄在其他的服务器上边,大家那边的bind-address地址在末端配置Postfix的时候须求相应的修改.然而为了安全起见,最棒照旧不要让数据库能够直接在外界能够访谈.

陈设实现了以往,大家则能够重启数据,使配置生效.

systemctl restart mariadb.service

配备完结了数据库以后,大家就必要布置Postfix,让其能够与玛丽亚DB协同职业.因为Postfix寻觅域名,客商账号等急需经过数据库来形成,不过其自己是不晓得怎么询问的,因此须求大家定制化.上面的布署中,把mys123123替换到前边数据库助理馆员设置的密码

/* This structure contains information about the holder of a semaphore */#ifdef CONFIG_PRIORITY_INHERITANCEstruct tcb_s; /* Forward reference */struct semholder_s{#if CONFIG_SEM_PREALLOCHOLDERS > 0 struct semholder_s *flink; /* Implements singly linked list */#endif FAR struct tcb_s *htcb; /* Holder TCB */ int16_t counts; /* Number of counts owned by this holder */};/* This is the generic semaphore structure. */struct sem_s{ volatile int16_t semcount; /* >0 -> Num counts available */ /* <0 -> Num tasks waiting for semaphore */ /* If priority inheritance is enabled, then we have to keep track of which * tasks hold references to the semaphore. */#ifdef CONFIG_PRIORITY_INHERITANCE uint8_t flags; /* See PRIOINHERIT_FLAGS_* definitions */# if CONFIG_SEM_PREALLOCHOLDERS > 0 FAR struct semholder_s *hhead; /* List of holders of semaphore counts */# else struct semholder_s holder; /* Single holder */# endif#endif};

按规矩,先来一张图吧:

Nuttx相关的历史篇章:

  • Nuttx Task Schedule
  • Nuttx时限信号机制

Nuttx在编写翻译在此之前必要先进行布置,而Nuttx是三个冲天可配备的RTOS,Nuttx的布局文件使用kconfig-frontends工具来保卫安全,配置工具将使用Kconfig文件,而Kconfig文件在Nuttx的代码文件夹中到处可知。每一个Kconfig文件包罗了布署变量的扬言,而每四个陈设变量又给Nuttx提供了一种配备选拔,Nuttx的结尾配置都由那一个Kconfig文本决定。日常举办Nuttx配置的时候,都足以在Nuttx根目录中经过make menuconfig一声令下来操作,前提是在根目录中须求有.config文本存在,而.config文本是从有个别特定的开拓板中的有些路径下拷贝过来的。

要获取.config文本,又有三种渠道:一种是通过手动将.configMake.defs文件从一定开拓板中的有个别路径中拷贝至Nuttx的顶层路径;一种是通过tools目录下的configure.sh剧本完成拷贝职业。最后在展开编写翻译的时候,供给依赖那八个文本。

  1. 手动配置
  • Copy configs/<board-name>/[<config-dir>/]Make.defs to ${TOPDIR}/Make.defs
  • Copy configs/<board-name>/[<config-dir>/]defconfig to ${TOPDIR}/.config
  1. 机动配置
  • tools/confiure.sh [OPTIONS] <board-name>[/<config-dir>]

每一个特定的开采板文件夹中都有七个文本Make.defsdefconfig文件来陈说该开拓板的铺排。

Make.defs

  1. Make.defs提供架交涉一定工具的营造选项,在编写翻译时它将被别的具有的Makefile富含,它将概念如下内容:
  • Tools: CC, LD, AR, NM, OBJCOPY, OBJDUMP
  • Tools options: CFLAGS, LDFLAGS
  1. Make.defs运行时,TOPDIR会传送给它,在Make.defs少校富含以下八个公文:
  • $/.config: Nuttx的配置
  • $/tools/Config.mk:一些通用的定义。tools/Config.mk文件中包罗了一部卓殊加的宏定义,那个宏定义的值在急需的时候大概会在特定架构中的Make.defs中被遮住,例如:COMPILE, ASSEMBLE, ARCHIVE, CLEAN, MKDEP等。

defconfigdefconfig文件中隐含部分如CONFIG_VARIABLE=value花样的概念,它拷贝至$路径下后,在编写翻译时会被其它Makefile所蕴藏,况且会用它来变化include/nuttx/config.h文件,那么些文件在众多C文件中会用到。

粗粗的目录组织如下:

图片 7客商发送邮件进程.png-19.1kB

  • CONFIG_SEM_PREALLOCHOLDERS率先,在Nuttx中,优先级继承是在POSIX时限信号量基础上落到实处的,那是因为这一个时域信号量是Nuttx中最原始的等候机制,别的超过半数等候格局都以凭仗信号量来促成的,由此,假诺为POSIX非时限信号量落成了优先级承袭,那么大许多Nuttx等待机制也就颇负那么些职能了。复杂性的产出是因为功率信号量大概有多数能量信号量计数持有者,为了落到实处全数持有者的优先级承接,必得分配内部数据结构来管理与确定性信号量关联的各类持有者。CONFIG_SEM_PREALLOCHOLDERS概念了对具有优先级承继协助的数字信号量实行计数的不如线程的最大额。这么些装置也定义了预分配数据结构池的轻重。如果禁止使用了优先级承继,也许只行使非频限信号量作为互斥体,也许使用计数非信号量的线程不超过五个,则能够将其安装为0.

  • CONFIG_SEM_NNESTPRIO别的,或许存在几个不等优先级的线程须要静观其变来自时限信号量的计数,低优先级线程持有实信号量必要被增加,不过又必得盯住全部进步优先级的值以便最后能恢复生机,那一个会让事情变得复杂。 CONFIG_SEM_NNESTPRIO概念数组的高低,每一个移动线程都有贰个数组。这几个值设置为等待另三个线程释放功率信号量上的高优先级线程的最大数量。

  • 给线程行为带来未知风险优先级继承相关的部分数据结构与非随机信号量的落成一体耦合在一同,大概带来一些影响。比方,假诺线程在时限信号量进行计数时进行;恐怕只要线程在不调用sem_destroy()时退出;或然优先级增加后的线程重新规定本身的预先级又会怎样。Nuttx在贯彻优先级承继的时候会尝试去管理全体的corner case,但是也很有极大大概会井底之蛙,最坏的情景是,内部存款和储蓄器在优先级承继的场所下冒出难点。

/* This represents one worker */struct kworker_s{ pid_t pid; /* The task ID of the worker thread */ volatile bool busy; /* True: Worker is not available */};/* This structure defines the state of one kernel-mode work queue */struct kwork_wqueue_s{ systime_t delay; /* Delay between polling cycles  */ struct dq_queue_s q; /* The queue of pending work */ struct kworker_s worker[1]; /* Describes a worker thread */};/* This structure defines the state of one high-priority work queue. This * structure must be cast-compatible with kwork_wqueue_s. */#ifdef CONFIG_SCHED_HPWORKstruct hp_wqueue_s{ systime_t delay; /* Delay between polling cycles  */ struct dq_queue_s q; /* The queue of pending work */ struct kworker_s worker[1]; /* Describes the single high priority worker */};#endif/* This structure defines the state of one high-priority work queue. This * structure must be cast compatible with kwork_wqueue_s */#ifdef CONFIG_SCHED_LPWORKstruct lp_wqueue_s{ systime_t delay; /* Delay between polling cycles  */ struct dq_queue_s q; /* The queue of pending work */ /* Describes each thread in the low priority queue's thread pool */ struct kworker_s worker[CONFIG_SCHED_LPNTHREADS];};#endif/**************************************************************************** * Public Data ****************************************************************************/#ifdef CONFIG_SCHED_HPWORK/* The state of the kernel mode, high priority work queue. */extern struct hp_wqueue_s g_hpwork;#endif#ifdef CONFIG_SCHED_LPWORK/* The state of the kernel mode, low priority work queue. */extern struct lp_wqueue_s g_lpwork;#endif

该接口会在调用Task中开发/创设叁个音讯队列,音信队列与调用Task建设构造联系,调用Task能够运用再次来到值来引用音信队列。在那之中oflags表示了不一样的意义,能够将那些位张开组合:

# These are configuration variables that are quoted by configuration tool# but which must be unquoated when used in the build system.# 调整架构相关宏的值,其中patsubst为Makefile匹配与替换函数,strip为去空格函数CONFIG_ARCH := $(patsubst "%",%,$(strip $(CONFIG_ARCH)))CONFIG_ARCH_CHIP := $(patsubst "%",%,$(strip $(CONFIG_ARCH_CHIP)))CONFIG_ARCH_BOARD := $(patsubst "%",%,$(strip $(CONFIG_ARCH_BOARD)))# Some defaults just to prohibit some bad behavior if for some reason they# are not definedOBJEXT ?= .oLIBEXT ?= .a# DELIM - Path segment delimiter character## Depends on this settings defined in board-specific defconfig file installed# at $/.config:## CONFIG_WINDOWS_NATIVE - Defined for a Windows native build# 定义DELIM分隔符ifeq ($(CONFIG_WINDOWS_NATIVE),y) DELIM = $else DELIM = $endif# INCDIR - Convert a list of directory paths to a list of compiler include# directirves# Example: CFFLAGS += ${shell $ [options] "compiler" "dir1" "dir2" "dir2" ...}## Note that the compiler string and each directory path string must quoted if# they contain spaces or any other characters that might get mangled by the# shell## Depends on this setting passed as a make commaond line definition from the# toplevel Makefile:## TOPDIR - The path to the top level NuttX directory in the form# appropriate for the current build environment## Depends on this settings defined in board-specific defconfig file installed# at $/.config:## CONFIG_WINDOWS_NATIVE - Defined for a Windows native buildifeq ($(CONFIG_WINDOWS_NATIVE),y) INCDIR = "$toolsincdir.bat"else INCDIR = "$/tools/incdir.sh"endif# PREPROCESS - Default macro to run the C pre-processor# Example: $(call PREPROCESS, in-file, out-file)## Depends on these settings defined in board-specific Make.defs file# installed at $/Make.defs:## CPP - The command to invoke the C pre-processor# CPPFLAGS - Options to pass to the C pre-processor# 预处理宏define PREPROCESS @echo "CPP: $1->$2" $ $ $1 -o $2endef# COMPILE - Default macro to compile one C file# Example: $(call COMPILE, in-file, out-file)## Depends on these settings defined in board-specific Make.defs file# installed at $/Make.defs:## CC - The command to invoke the C compiler# CFLAGS - Options to pass to the C compilerdefine COMPILE @echo "CC: $1" $ -c $ $1 -o $2endef# COMPILEXX - Default macro to compile one C++ file# Example: $(call COMPILEXX, in-file, out-file)## Depends on these settings defined in board-specific Make.defs file# installed at $/Make.defs:## CXX - The command to invoke the C++ compiler# CXXFLAGS - Options to pass to the C++ compilerdefine COMPILEXX @echo "CXX: $1" $ -c $ $1 -o $2endef# ASSEMBLE - Default macro to assemble one assembly language file# Example: $(call ASSEMBLE, in-file, out-file)## NOTE that the most common toolchain, GCC, uses the compiler to assemble# files because this has the advantage of running the C Pre-Processor against# the assembly language files. This is not possible with other toolchains;# platforms using those other tools should define AS and over-ride this# definition in order to use the assembler directly.## Depends on these settings defined in board-specific Make.defs file# installed at $/Make.defs:## CC - By default, the C compiler is used to compile assembly language# files# AFLAGS - Options to pass to the C+compilerdefine ASSEMBLE @echo "AS: $1" $ -c $ $1 -o $2endef# MOVEOBJ - Default macro to move an object file to the correct location# Example: $(call MOVEOBJ, prefix, directory)## This is only used in directories that keep object files in sub-directories.# Certain compilers  always place the resulting files in the the# directory where the compiler was invoked with not option to generate objects# in a different location.define MOVEOBJendef# ARCHIVE - Add a list of files to an archive# Example: $(call ARCHIVE, archive-file, "file1 file2 file3 ...")## Note: The fileN strings may not contain spaces or characters that may be# interpreted strangely by the shell## Depends on these settings defined in board-specific Make.defs file# installed at $/Make.defs:## AR - The command to invoke the archiver (includes any options)## Depends on this settings defined in board-specific defconfig file installed# at $/.config:## CONFIG_WINDOWS_NATIVE - Defined for a Windows native buildifeq ($(CONFIG_WINDOWS_NATIVE),y)define ARCHIVE @echo AR: $2 $ $1 $endefelsedefine ARCHIVE @echo "AR: $2" $ $1 $ || { echo "$ $1 FAILED!" ; exit 1 ; }endefendif# PRELINK - Prelink a list of files# This is useful when files were compiled with fvisibility=hidden.# Any symbol which was not explicitly made global is invisible outside the# prelinked file.## Example: $(call PRELINK, prelink-file, "file1 file2 file3 ...")## Note: The fileN strings may not contain spaces or characters that may be# interpreted strangely by the shell## Depends on these settings defined in board-specific Make.defs file# installed at $/Make.defs:## LD - The command to invoke the linker (includes any options)# OBJCOPY - The command to invoke the object cop (includes any options)## Depends on this settings defined in board-specific defconfig file installed# at $/.config:## CONFIG_WINDOWS_NATIVE - Defined for a Windows native buildifeq ($(CONFIG_WINDOWS_NATIVE),y)define PRELINK @echo PRELINK: $1 $ -Ur -o $1 $2 && $ --localize-hidden $1endefelsedefine PRELINK @echo "PRELINK: $1" $ -Ur -o $1 $2 && $ --localize-hidden $1endefendif# DELFILE - Delete one fileifeq ($(CONFIG_WINDOWS_NATIVE),y)define DELFILE $ if exist $1 (del /f /q $1)endefelsedefine DELFILE $ rm -f $1endefendif# DELDIR - Delete one directoryifeq ($(CONFIG_WINDOWS_NATIVE),y)define DELDIR $ if exist $1 (rmdir /q /s $1)endefelsedefine DELDIR $ rm -rf $1endefendif# MOVEFILE - Move one fileifeq ($(CONFIG_WINDOWS_NATIVE),y)define MOVEFILE $ if exist $1 (move /Y $1 $2)endefelsedefine MOVEFILE $ mv -f $1 $2endefendif# CLEAN - Default clean targetifeq ($(CONFIG_WINDOWS_NATIVE),y)define CLEAN $ if exist *$ (del /f /q *$ $ if exist *$ (del /f /q *$ $ if exist *~ (del /f /q *~) $ if exist (del /f /q .*.swp)endefelsedefine CLEAN $ rm -f *$ *$ *~ .*.swpendefendif

成立客户

接下去,大家在MariaDB中的邮箱中进入新的顾客,用作日常邮件的发送.这里的顾客密码不要采纳明文存款和储蓄.

USE mail;INSERT INTO domains  VALUES ('yusengy.info');INSERT INTO users (email, password) VALUES ('yusen@yusengy.info', ENCRYPT);quit

到这一年,我们的邮件服务器基本就已经搭建完结了,接下去只要利用MUA实行连接,就会像正常的邮件服务器同样使用了.

图片 8MUA配置

尝试给和睦的QQ邮箱发件看看.是否收纳了?

图片 9邮件截图

万一被拒绝接收或许在垃圾桶中,表明大家的邮件发送服务器信誉非常不够,这年我们须求给我们的邮件服务器做一些准则,举例加多SPF, DKIM以及DMARC等,以压实邮件发送的成功率,当这几个成就之后,基本能够一贯发送到收件箱了.具体能够仿照效法这一篇文章邮件服务器增添SPF,DKIM,DMARC,PTLAND

于今,二个邮件服务器的搭建就形成了,通过这一多种的操作,是或不是对此电子邮件协议又有了更加的精晓吧?若无在收件箱收到发送的邮件,能够在垃圾箱看看,只怕看看是或不是退件了.那篇作品中我们一向不聊到SPF, DKIM以及DMARC申明的布置,因此有十分大希望会被QQ邮箱退件的,毕竟现实中的邮件服务器还亟需一多级的安排,以加强送达率.那些小编在后头会开一篇文章特地讲明.假诺MUA提示发件失利,那么大家得以查看一下日记,分别在/var/log/maillog以及/home/vmail/dovecot-deliver.log,找到呼应的一无所长,然后回来小说相应的地点看看是还是不是陈设错了.如若还不能解决,可留言私信,小编见到了会进展对应的解答.

sem_post()

之所以做事行列的天职管理主题是work_process()接口,该接口对于基本的高优先级职业行列和内核低优先级工作行列是一模一样的。

/**************************************************************************** * Name: mq_timedsend * * Description: * This function adds the specificied message  to the message queue * . The "msglen" parameter specifies the length of the message * in bytes pointed to by "msg." This length must not exceed the maximum * message length from the mq_getattr(). * * If the message queue is not full, mq_timedsend() place the message in the * message queue at the position indicated by the "prio" argrument. * Messages with higher priority will be inserted before lower priority * messages. The value of "prio" must not exceed MQ_PRIO_MAX. * * If the specified message queue is full and O_NONBLOCK is not set in the * message queue, then mq_timedsend() will block until space becomes available * to the queue the message or a timeout occurs. * * mq_timedsend() behaves just like mq_send(), except that if the queue * is full and the O_NONBLOCK flag is not enabled for the message queue * description, then abstime points to a structure which specifies a * ceiling on the time for which the call will block. This ceiling is an * absolute timeout in seconds and nanoseconds since the Epoch (midnight * on the morning of 1 January 1970). * * If the message queue is full, and the timeout has already expired by * the time of the call, mq_timedsend() returns immediately. * * Parameters: * mqdes - Message queue descriptor * msg - Message to send * msglen - The length of the message in bytes * prio - The priority of the message * abstime - the absolute time to wait until a timeout is decleared * * Return Value: * On success, mq_send() returns 0 ; on error, -1  * is returned, with errno set to indicate the error: * * EAGAIN The queue was empty, and the O_NONBLOCK flag was set for the * message queue description referred to by mqdes. * EINVAL Either msg or mqdes is NULL or the value of prio is invalid. * EPERM Message queue opened not opened for writing. * EMSGSIZE 'msglen' was greater than the maxmsgsize attribute of the * message queue. * EINTR The call was interrupted by a signal handler. * * Assumptions/restrictions: * ****************************************************************************/int mq_timedsend(mqd_t mqdes, FAR const char *msg, size_t msglen, int prio, FAR const struct timespec *abstime){ FAR struct tcb_s *rtcb = this_task(); FAR struct mqueue_inode_s *msgq; FAR struct mqueue_msg_s *mqmsg = NULL; irqstate_t flags; int ticks; int result; int ret = ERROR; DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL); /* mq_timedsend() is a cancellation point */ enter_cancellation_point(); /* Verify the input parameters -- setting errno appropriately * on any failures to verify. */ if (mq_verifysend(mqdes, msg, msglen, prio) != OK) { /* mq_verifysend() will set the errno appropriately */ leave_cancellation_point(); return ERROR; } /* Pre-allocate a message structure */ mqmsg = mq_msgalloc(); if (mqmsg == NULL) { /* Failed to allocate the message. mq_msgalloc() does not set the * errno value. */ set_errno; leave_cancellation_point(); return ERROR; } /* Get a pointer to the message queue */ sched_lock(); msgq = mqdes->msgq; /* OpenGroup.org: "Under no circumstance shall the operation fail with a * timeout if there is sufficient room in the queue to add the message * immediately. The validity of the abstime parameter need not be checked * when there is sufficient room in the queue." * * Also ignore the time value if for some crazy reason we were called from * an interrupt handler. This probably really should be an assertion. * * NOTE: There is a race condition here: What if a message is added by * interrupt related logic so that queue again becomes non-empty. That * is handled because mq_dosend() will permit the maxmsgs limit to be * exceeded in that case. */ if (msgq->nmsgs < msgq->maxmsgs || up_interrupt_context { /* Do the send with no further checks (possibly exceeding maxmsgs) * Currently mq_dosend() always returns OK. */ ret = mq_dosend(mqdes, mqmsg, msg, msglen, prio); sched_unlock(); leave_cancellation_point(); return ret; } /* The message queue is full... We are going to wait. Now we must have a * valid time value. */ if (!abstime || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { result = EINVAL; goto errout_with_mqmsg; } /* Create a watchdog. We will not actually need this watchdog * unless the queue is full, but we will reserve it up front * before we enter the following critical section. */ rtcb->waitdog = wd_create(); if (!rtcb->waitdog) { result = EINVAL; goto errout_with_mqmsg; } /* We are not in an interrupt handler and the message queue is full. * Set up a timed wait for the message queue to become non-full. * * Convert the timespec to clock ticks. We must have interrupts * disabled here so that this time stays valid until the wait begins. */ flags = enter_critical_section(); result = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); /* If the time has already expired and the message queue is empty, * return immediately. */ if (result == OK && ticks <= 0) { result = ETIMEDOUT; } /* Handle any time-related errors */ if (result != OK) { goto errout_in_critical_section; } /* Start the watchdog and begin the wait for MQ not full */ wd_start(rtcb->waitdog, ticks, (wdentry_t)mq_sndtimeout, 1, getpid; /* And wait for the message queue to be non-empty */ ret = mq_waitsend; /* This may return with an error and errno set to either EINTR * or ETIMEOUT. Cancel the watchdog timer in any event. */ wd_cancel(rtcb->waitdog); /* Check if mq_waitsend() failed */ if (ret < 0) { /* mq_waitsend() will set the errno, but the error exit will reset it */ result = get_errno(); goto errout_in_critical_section; } /* That is the end of the atomic operations */ leave_critical_section; /* If any of the above failed, set the errno. Otherwise, there should * be space for another message in the message queue. NOW we can allocate * the message structure. * * Currently mq_dosend() always returns OK. */ ret = mq_dosend(mqdes, mqmsg, msg, msglen, prio); sched_unlock(); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; leave_cancellation_point(); return ret;/* Exit here with  the scheduler locked,  a message allocated,  a * wdog allocated, and  interrupts disabled. The error code is in * 'result' */errout_in_critical_section: leave_critical_section; wd_delete(rtcb->waitdog); rtcb->waitdog = NULL;/* Exit here with  the scheduler locked and 2) a message allocated. The * error code is in 'result' */errout_with_mqmsg: mq_msgfree; sched_unlock(); set_errno; leave_cancellation_point(); return ERROR;}

/**************************************************************************** * Name: mq_timedreceive * * Description: * This function receives the oldest of the highest priority messages from * the message queue specified by "mqdes." If the size of the buffer in * bytes  is less than the "mq_msgsize" attribute of the message * queue, mq_timedreceive will return an error. Otherwise, the selected * message is removed from the queue and copied to "msg." * * If the message queue is empty and O_NONBLOCK was not set, * mq_timedreceive() will block until a message is added to the message * queue (or until a timeout occurs). If more than one task is waiting * to receive a message, only the task with the highest priority that has * waited the longest will be unblocked. * * mq_timedreceive() behaves just like mq_receive(), except that if the * queue is empty and the O_NONBLOCK flag is not enabled for the message * queue description, then abstime points to a structure which specifies a * ceiling on the time for which the call will block. This ceiling is an * absolute timeout in seconds and nanoseconds since the Epoch (midnight * on the morning of 1 January 1970). * * If no message is available, and the timeout has already expired by the * time of the call, mq_timedreceive() returns immediately. * * Parameters: * mqdes - Message Queue Descriptor * msg - Buffer to receive the message * msglen - Size of the buffer in bytes * prio - If not NULL, the location to store message priority. * abstime - the absolute time to wait until a timeout is declared. * * Return Value: * One success, the length of the selected message in bytes is returned. * On failure, -1  is returned and the errno is set appropriately: * * EAGAIN The queue was empty, and the O_NONBLOCK flag was set * for the message queue description referred to by 'mqdes'. * EPERM Message queue opened not opened for reading. * EMSGSIZE 'msglen' was less than the maxmsgsize attribute of the * message queue. * EINTR The call was interrupted by a signal handler. * EINVAL Invalid 'msg' or 'mqdes' or 'abstime' * ETIMEDOUT The call timed out before a message could be transferred. * * Assumptions: * ****************************************************************************/ssize_t mq_timedreceive(mqd_t mqdes, FAR char *msg, size_t msglen, FAR int *prio, FAR const struct timespec *abstime){ FAR struct tcb_s *rtcb = this_task(); FAR struct mqueue_msg_s *mqmsg; irqstate_t flags; int ret = ERROR; DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL); /* mq_timedreceive() is a cancellation point */ enter_cancellation_point(); /* Verify the input parameters and, in case of an error, set * errno appropriately. */ if (mq_verifyreceive(mqdes, msg, msglen) != OK) { leave_cancellation_point(); return ERROR; } if (!abstime || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { set_errno; leave_cancellation_point(); return ERROR; } /* Create a watchdog. We will not actually need this watchdog * unless the queue is not empty, but we will reserve it up front * before we enter the following critical section. */ rtcb->waitdog = wd_create(); if (!rtcb->waitdog) { set_errno; leave_cancellation_point(); return ERROR; } /* Get the next message from the message queue. We will disable * pre-emption until we have completed the message received. This * is not too bad because if the receipt takes a long time, it will * be because we are blocked waiting for a message and pre-emption * will be re-enabled while we are blocked */ sched_lock(); /* Furthermore, mq_waitreceive() expects to have interrupts disabled * because messages can be sent from interrupt level. */ flags = enter_critical_section(); /* Check if the message queue is empty. If it is NOT empty, then we * will not need to start timer. */ if (mqdes->msgq->msglist.head == NULL) { int ticks; /* Convert the timespec to clock ticks. We must have interrupts * disabled here so that this time stays valid until the wait begins. */ int result = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks); /* If the time has already expired and the message queue is empty, * return immediately. */ if (result == OK && ticks <= 0) { result = ETIMEDOUT; } /* Handle any time-related errors */ if (result != OK) { leave_critical_section; sched_unlock(); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; set_errno; leave_cancellation_point(); return ERROR; } /* Start the watchdog */ wd_start(rtcb->waitdog, ticks, (wdentry_t)mq_rcvtimeout, 1, getpid; } /* Get the message from the message queue */ mqmsg = mq_waitreceive; /* Stop the watchdog timer (this is not harmful in the case where * it was never started) */ wd_cancel(rtcb->waitdog); /* We can now restore interrupts */ leave_critical_section; /* Check if we got a message from the message queue. We might * not have a message if: * * - The message queue is empty and O_NONBLOCK is set in the mqdes * - The wait was interrupted by a signal * - The watchdog timeout expired */ if  { ret = mq_doreceive(mqdes, mqmsg, msg, prio); } sched_unlock(); wd_delete(rtcb->waitdog); rtcb->waitdog = NULL; leave_cancellation_point(); return ret;}

/**************************************************************************** * Name: mq_sndtimeout * * Description: * This function is called if the timeout elapses before the message queue * becomes non-full. * * Parameters: * argc - the number of arguments (should be 1) * pid - the task ID of the task to wakeup * * Return Value: * None * * Assumptions: * ****************************************************************************/static void mq_sndtimeout(int argc, wdparm_t pid){ FAR struct tcb_s *wtcb; irqstate_t flags; /* Disable interrupts. This is necessary because an interrupt handler may * attempt to send a message while we are doing this. */ flags = enter_critical_section(); /* Get the TCB associated with this pid. It is possible that task may no * longer be active when this watchdog goes off. */ wtcb = sched_gettcbpid); /* It is also possible that an interrupt/context switch beat us to the * punch and already changed the task's state. */ if (wtcb && wtcb->task_state == TSTATE_WAIT_MQNOTFULL) { /* Restart with task with a timeout error */ mq_waitirq(wtcb, ETIMEDOUT); } /* Interrupts may now be re-enabled. */ leave_critical_section;}

/**************************************************************************** * Name: mq_rcvtimeout * * Description: * This function is called if the timeout elapses before the message queue * becomes non-empty. * * Parameters: * argc - the number of arguments (should be 1) * pid - the task ID of the task to wakeup * * Return Value: * None * * Assumptions: * ****************************************************************************/static void mq_rcvtimeout(int argc, wdparm_t pid){ FAR struct tcb_s *wtcb; irqstate_t flags; /* Disable interrupts. This is necessary because an interrupt handler may * attempt to send a message while we are doing this. */ flags = enter_critical_section(); /* Get the TCB associated with this pid. It is possible that task may no * longer be active when this watchdog goes off. */ wtcb = sched_gettcbpid); /* It is also possible that an interrupt/context switch beat us to the * punch and already changed the task's state. */ if (wtcb && wtcb->task_state == TSTATE_WAIT_MQNOTEMPTY) { /* Restart with task with a timeout error */ mq_waitirq(wtcb, ETIMEDOUT); } /* Interrupts may now be re-enabled. */ leave_critical_section;}

/**************************************************************************** * Name: mq_waitirq * * Description: * This function is called when a signal or a timeout is received by a * task that is waiting on a message queue -- either for a queue to * becoming not full (on mq_send) or not empty (on mq_receive). * * Parameters: * wtcb - A pointer to the TCB of the task that is waiting on a message * queue, but has received a signal instead. * * Return Value: * None * * Assumptions: * ****************************************************************************/void mq_waitirq(FAR struct tcb_s *wtcb, int errcode){ FAR struct mqueue_inode_s *msgq; irqstate_t flags; /* Disable interrupts. This is necessary because an interrupt handler may * attempt to send a message while we are doing this. */ flags = enter_critical_section(); /* It is possible that an interrupt/context switch beat us to the punch and * already changed the task's state. NOTE: The operations within the if * are safe because interrupts are always disabled with the msgwaitq, * nwaitnotempty, and nwaitnotfull fields are modified. */ if (wtcb->task_state == TSTATE_WAIT_MQNOTEMPTY || wtcb->task_state == TSTATE_WAIT_MQNOTFULL) { /* Get the message queue associated with the waiter from the TCB */ msgq = wtcb->msgwaitq; DEBUGASSERT; wtcb->msgwaitq = NULL; /* Decrement the count of waiters and cancel the wait */ if (wtcb->task_state == TSTATE_WAIT_MQNOTEMPTY) { DEBUGASSERT(msgq->nwaitnotempty > 0); msgq->nwaitnotempty--; } else { DEBUGASSERT(msgq->nwaitnotfull > 0); msgq->nwaitnotfull--; } /* Mark the errno value for the thread. */ wtcb->pterrno = errcode; /* Restart the task. */ up_unblock_task; } /* Interrupts may now be enabled. */ leave_critical_section;}
# All add-on directories.## NUTTX_ADDONS is the list of directories built into the NuttX kernel.# USER_ADDONS is the list of directories that will be built into the user# applicationNUTTX_ADDONS :=USER_ADDONS :=# In the protected build, the applications in the apps/ directory will be# into the userspace; in the flat build, the applications will b built into# the kernel space. But in the kernel build, the applications will not be# built at all by this Makefile.ifeq ($(CONFIG_BUILD_PROTECTED),y)USER_ADDONS += $elseifneq ($(CONFIG_BUILD_KERNEL),y)NUTTX_ADDONS += $endifendif# Lists of build directories.## FSDIRS depend on file descriptor support; NONFSDIRS do not (except for parts# of FSDIRS). We will exclude FSDIRS from the build if file descriptor# support is disabled. NOTE that drivers, in general, depends on file# descriptor support but is always built because there are other components# in the drivers directory that are needed even if file descriptors are not# supported.# CONTEXTDIRS include directories that have special, one-time pre-build# requirements. Normally this includes things like auto-generation of# configuration specific files or creation of configurable symbolic links# USERDIRS - When NuttX is build is a monolithic kernel, this provides the# list of directories that must be built# OTHERDIRS - These are directories that are not built but probably should# be cleaned to prevent garbage from collecting in them when changing# configurations.NONFSDIRS = sched drivers configs $ $(NUTTX_ADDONS)FSDIRS = fs binfmtCONTEXTDIRS = configs $USERDIRS =OTHERDIRS = libifeq ($(CONFIG_BUILD_PROTECTED),y)USERDIRS += libc mm $(USER_ADDONS)ifeq ($(CONFIG_HAVE_CXX),y)USERDIRS += libxxendifelseifeq ($(CONFIG_BUILD_KERNEL),y)USERDIRS += libc mmifeq ($(CONFIG_HAVE_CXX),y)USERDIRS += libxxendifelseNONFSDIRS += libc mmOTHERDIRS += $(USER_ADDONS)ifeq ($(CONFIG_HAVE_CXX),y)NONFSDIRS += libxxelseOTHERDIRS += libxxendifendifendififeq ($(CONFIG_LIB_SYSCALL),y)NONFSDIRS += syscallCONTEXTDIRS += syscallUSERDIRS += syscallelseOTHERDIRS += syscallendififeq ($(CONFIG_LIB_ZONEINFO_ROMFS),y)CONTEXTDIRS += libcendififeq ($(CONFIG_NX),y)NONFSDIRS += graphics libnxCONTEXTDIRS += graphics libnxelseOTHERDIRS += graphics libnxendififeq ($(CONFIG_AUDIO),y)NONFSDIRS += audioelseOTHERDIRS += audioendififeq ($(CONFIG_DRIVERS_WIRELESS),y)NONFSDIRS += wirelesselseOTHERDIRS += wirelessendif# CLEANDIRS are the directories that will clean in. These are# all directories that we know about.# KERNDEPDIRS are the directories in which we will build target dependencies.# If NuttX and applications are built separately (CONFIG_BUILD_PROTECTED or# CONFIG_BUILD_KERNEL), then this holds only the directories containing# kernel files.# USERDEPDIRS. If NuttX and applications are built separately (CONFIG_BUILD_PROTECTED),# then this holds only the directories containing user files. If# CONFIG_BUILD_KERNEL is selected, then applications are not build at all.CLEANDIRS = $(NONFSDIRS) $ $ $(OTHERDIRS)KERNDEPDIRS = $(NONFSDIRS)USERDEPDIRS = $# Add file system directories to KERNDEPDIRS (they are already in CLEANDIRS)ifeq ($(CONFIG_NFILE_DESCRIPTORS),0)ifeq ($(CONFIG_NET),y)ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0)KERNDEPDIRS += fsendifKERNDEPDIRS += driversendifelseKERNDEPDIRS += $endif# Add networking directories to KERNDEPDIRS and CLEANDIRSifeq ($(CONFIG_NET),y)KERNDEPDIRS += netendifCLEANDIRS += netifeq ($(CONFIG_CRYPTO),y)KERNDEPDIRS += cryptoendifCLEANDIRS += crypto

创设虚构域名配置

创建:/etc/postfix/mysql-virtual_domains.cf

user = mail_adminpassword = mys123123dbname = mailquery = SELECT domain AS virtual FROM domains WHERE domain='%s'hosts = 127.0.0.1

全部来讲,在Nuttx中复信号量既可用以共同和排斥管理,当职责等不到连续信号量时,便增加到相关的职分队列中开展围堵睡眠,当释放时域信号量时,再去该职务队列中展开查询,重新调整该职务实施。假若境遇优先级反转的景况,优先级承袭是一种缓和方式。

图片 10行事行列

该接口能够用于获取mqdes新闻队列的气象消息。富含消息队列的最大容积、音讯的最大尺寸、Flags以及当前队列中国国投息的数据等。

# 包含需要依赖的文件include ${TOPDIR}/.config include ${TOPDIR}/tools/Config.mk include ${TOPDIR}/arch/arm/src/arm/Toolchain.defsifeq ($,y) # Windows-native toolchains DIRLINK = $/tools/copydir.sh DIRUNLINK = $/tools/unlink.sh MKDEP = $/tools/mkwindeps.sh ARCHINCLUDES = -I. -isystem "${shell cygpath -w $/include}" ARCHXXINCLUDES = -I. -isystem "${shell cygpath -w $/include}" -isystem "${shell cygpath -w $/include/cxx}" ARCHSCRIPT = -T "${shell cygpath -w $/configs/$(CONFIG_ARCH_BOARD)/scripts/ld.script}"else # Linux/Cygwin-native toolchain 在Linux环境下使用的工具链 MKDEP = $/tools/mkdeps$(HOSTEXEEXT) ARCHINCLUDES = -I. -isystem $/include ARCHXXINCLUDES = -I. -isystem $/include -isystem $/include/cxx -isystem $/include/uClibc++ ARCHSCRIPT = -T$/configs/<board-name>/$(CONFIG_ARCH_BOARD)/scripts/ld.scriptendif# 定义工具,其中$在$/arch/arm/src/arm/Toolchain.defs文件中定义CC = $gccCXX = $g++CPP = $gcc -ELD = $ldAR = $ar rcsNM = $nmOBJCOPY = $objcopyOBJDUMP = $objdump# 编译器版本ARCHCCVERSION = ${shell $ -v 2>&1 | sed -n '/^gcc version/p' | sed -e 's/^gcc version /1/g' -e 's/[- ].*//g' -e '1q'}ARCHCCMAJOR = ${shell echo $(ARCHCCVERSION) | cut -d'.' -f1}ifeq ($(CONFIG_DEBUG_SYMBOLS),y) ARCHOPTIMIZATION = -g ARCHOPTIMIZATION += -fno-omit-frame-pointer -mapcs -mno-sched-prologendififneq ($(CONFIG_DEBUG_NOOPT),y) ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointerendififeq ($(ARCHCCMAJOR),4) ARCHCPUFLAGS = -mtune=arm9tdmi -march=armv5te -mfloat-abi=soft -fno-builtinelse ARCHCPUFLAGS = -mapcs-32 -mtune=arm9tdmi -march=armv5te -msoft-float -fno-builtinendifARCHCFLAGS = -fno-builtinARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new -fpermissive -fno-rttiARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -WundefARCHWARNINGSXX = -Wall -Wshadow -WundefARCHDEFINES =ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10# 定义所有编译时的FLAG选项CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipeCPICFLAGS = $(ARCHPICFLAGS) $CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -std=c++11 -pipeCXXPICFLAGS = $(ARCHPICFLAGS) $CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES)AFLAGS = $ -D__ASSEMBLY__NXFLATLDFLAGS1 = -r -d -warn-commonNXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$/binfmt/libnxflat/gnu-nxflat-gotoff.ld -no-check-sectionsLDNXFLATFLAGS = -e main -s 2048# 定义文件后缀ASMEXT = .SOBJEXT = .oLIBEXT = .aEXEEXT =ifneq ($(CONFIG_ARM_TOOLCHAIN),BUILDROOT) LDFLAGS += -nostartfiles -nodefaultlibsendififeq ($(CONFIG_DEBUG_SYMBOLS),y) LDFLAGS += -gendif# 定义Host的编译器HOSTCC = gccHOSTINCLUDES = -I.HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipeHOSTLDFLAGS =

设置hostname

CentOS7,能够通过hostnamectl set-hostname hostname一声令下设置hostname,何况修改hosts文件.这里域名是yusengy.info.

hostnamectl set-hostname mail.yusengy.info

为何要安装hostname呢?因为相似景况下,Postfix在与任何的SMTP服务器进行通讯的时候,会使用hostname来表名本身的身份.主机名有两种方式,单名字FQDN(Fully Qualified Domain Name).假设SMTP服务器不是用FQDN来表明身份,则有十分的大可能率会被拒绝接收.

sem_wait()

简单易行来讲,职业行列就好像上海教室所示,由八个部分组成:

  1. 消息发送函数

顶层目录中的Makefile,通过make -C逐层步向子目录中,施行相应的编写翻译动作,最后找到全部的依据关系,生成nuttxnuttx.bin文本。apps目录中的编写翻译方式也类似,从apps/Makefile开头深入分析即可。

MTA: Mail Transfer Protocol.邮件传输代理,是SMTP的一种达成.常用的MTA有sendmail,Postfix.本例中利用Postfix.MTA仅仅肩负邮件的传导,MDA担任把接受到的邮件保存在硬盘中.

Nuttx相关的野史篇章:

  • Nuttx Task Schedule
  • Nuttx随机信号机制
  • Nuttx编写翻译系统
  • Nuttx音信队列机制

在选择API进行开拓的时候,要求包涵头文件#include <mqueue.h>

Config.mk文件中,定义了如PREPROCESS, COMPILE, COMPILEXX, ASSEMBLE, ARCHIVE, DELFILE等通用宏,在任何文件准将使用$(call XXX, in-file, out-file)情势来采用,当中XXX意味着定义的那些宏。

Postfix:三个开源的MTA服务器,担当通过SMTP左券管理发送到本机的邮件以及由本机向外发送的邮件.与sendMail相似.现今盛行的服务器套件举个例子Zimbra,IRedMail内部都选择Postfix作为MTA.

sem_wait()函数主要完毕以下几个办事:

有二种不一致品类的劳作行列,种种都有两样的属性和用途。

  1. 调用inode_find()接口去询问是还是不是业已存在一个音信队列对应的inode了,由于音信队列都会对应到二个文件节点,比方"/var/mqueue/my_mq",供给为消息队列创造inode。如果mq_open()开采的是已有个别消息队列,那么inode_find()就能够找到相应的节点,不然就须求调用inode_reserve()去创建。
  2. 假如音信队列不真实,除了成立inode之外,还须求调用mq_descreate()接口创立信息队列描述符,mq_descreate()接口中调用mq_desalloc(),从全局队列中挪取描述符节点,并参与到struct tcb_s结构中,那几个在上图中也能看出来。
  3. 调用mq_msgqalloc()接口,创造四个新闻队列,并将新闻队列与mq_descreate()赢得的音信队列描述符实行绑定。最终更新更新inode的信息。关键代码如下:
...# Build Setup## CONFIG_EXPERIMENTAL is not set# CONFIG_DEFAULT_SMALL is not setCONFIG_HOST_LINUX=y# CONFIG_HOST_OSX is not set# CONFIG_HOST_WINDOWS is not set# CONFIG_HOST_OTHER is not set## Build Configuration#CONFIG_APPS_DIR="../apps"CONFIG_BUILD_FLAT=y# CONFIG_BUILD_2PASS is not set...

开创电子邮件与公事映射

创建:/etc/postfix/mysql-virtual_email2email.cf

user = mail_adminpassword = mys123123dbname = mailquery = SELECT email FROM users WHERE email='%s'hosts = 127.0.0.1

创建达成之后修改权限以及分配顾客组.

chmod o= /etc/postfix/mysql-virtual_*.cfchgrp postfix /etc/postfix/mysql-virtual_*.cf

再者,我们创立一个新的客户组以及客商,用来管理邮件.全部的杜撰邮箱,都会存在这么些客户的home目录下.

groupadd -g 5000 vmailuseradd -g vmail -u 5000 vmail -d /home/vmail -m

接下去,大家对Postfix总体进展配置.把下部的mail.yusengy.info替换到你的hostname.假诺你指望利用自个儿的SSL证书,则把/etc/pki/dovecot/private/dovecot.pem替换来你的证书路线.

postconf -e 'myhostname = mail.yusengy.info'postconf -e 'mydestination = localhost, localhost.localdomain'postconf -e 'mynetworks = 127.0.0.0/8'postconf -e 'inet_interfaces = all'postconf -e 'message_size_limit = 30720000'postconf -e 'virtual_alias_domains ='postconf -e 'virtual_alias_maps = proxy:mysql:/etc/postfix/mysql-virtual_forwardings.cf, mysql:/etc/postfix/mysql-virtual_email2email.cf'postconf -e 'virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql-virtual_domains.cf'postconf -e 'virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql-virtual_mailboxes.cf'postconf -e 'virtual_mailbox_base = /home/vmail'postconf -e 'virtual_uid_maps = static:5000'postconf -e 'virtual_gid_maps = static:5000'postconf -e 'smtpd_sasl_type = dovecot'postconf -e 'smtpd_sasl_path = private/auth'postconf -e 'smtpd_sasl_auth_enable = yes'postconf -e 'broken_sasl_auth_clients = yes'postconf -e 'smtpd_sasl_authenticated_header = yes'postconf -e 'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination'postconf -e 'smtpd_use_tls = yes'postconf -e 'smtpd_tls_cert_file = /etc/pki/dovecot/certs/dovecot.pem'postconf -e 'smtpd_tls_key_file = /etc/pki/dovecot/private/dovecot.pem'postconf -e 'virtual_create_maildirsize = yes'postconf -e 'virtual_maildir_extended = yes'postconf -e 'proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $virtual_mailbox_limit_maps'postconf -e 'virtual_transport = dovecot'postconf -e 'dovecot_destination_recipient_limit = 1'

修改Postfix配置,添加Dovecot服务.修改:/etc/postfix/master.cf

dovecot unix - n n - - pipe flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}

submission以及smtps部分给反注释了,让这一部分代码生效.

图片 11陈设截图重启Postfix,至此,Postfix就主题配备好了.

systemctl enable postfix.servicesystemctl start postfix.service

修改:/etc/dovecot/dovecot.conf此处把域名yusengy.info替换来自身安排的域名.

protocols = imap pop3log_timestamp = "%Y-%m-%d %H:%M:%S "mail_location = maildir:/home/vmail/%d/%n/Maildirssl_cert = </etc/pki/dovecot/certs/dovecot.pemssl_key = </etc/pki/dovecot/private/dovecot.pemnamespace { type = private separator = . prefix = INBOX. inbox = yes}service auth { unix_listener auth-master { mode = 0600 user = vmail } unix_listener /var/spool/postfix/private/auth { mode = 0666 user = postfix group = postfix }user = root}service auth-worker { user = root}protocol lda { log_path = /home/vmail/dovecot-deliver.log auth_socket_path = /var/run/dovecot/auth-master postmaster_address = postmaster@yusengy.info}

因为数据库存款和储蓄有客商的账号密码音讯,Dovecot的职分之一正是注脚顾客的账号密码,因而大家还须要创制一个布署文件以让Dovecot与数据库进行交互.老惯例,这里也是把密码实行沟通一下.成立:/etc/dovecot/dovecot-sql.conf.ext

driver = mysqlconnect = host=127.0.0.1 dbname=mail user=mail_admin password=mys123123default_pass_scheme = CRYPTpassword_query = SELECT email as user, password FROM users WHERE email='%u';

修改文件所属的客商组以及拜望权限

chgrp dovecot /etc/dovecot/dovecot-sql.conf.extchmod o= /etc/dovecot/dovecot-sql.conf.ext

安装Dovecot在开启运行何况运转其服务

systemctl enable dovecot.servicesystemctl start dovecot.service

然后大家注重一下var/log/maillog,明确现在Dovecot没有不当

图片 12Dovecot日志

下一场大家运用Telnet检查评定一下pop3服务是还是不是符合规律.

yum install telnettelnet localhost pop3

假使您看看的和本身看见的大都,那么评释是pop3服务是正规的.

图片 13pop3服务

  • int sem_init(sem_t *sem, int pshared, unsigned int value)完了未命名复信号量sem的发轫化,pshared未使用,value为时域信号量的开始化值。实现开头化之后,频域信号量就会被用来sem_wait()/sem_post()/sem_trywait()等接口了。

  • int sem_destroy(sem_t *sem)完了未命名复信号量sem的绝迹,独有调用sem_init()接口创制的非时域信号量,技艺被sem_destroy()销毁。调用sem_destroy() 去销毁二个命名时限信号量的行事是未定义的,在sem_destroy()而后再去行使实信号量的一颦一笑也是未定义的。

  • sem_t *sem_open(const char *name, int oflag, ...)Task和命名信号量之间创设一个连接,在动用复信号量名称调用sem_open()之后,关联的Task能够使用该函数的回来地址来援引对应的随机信号量。

  • int sem_close(sem_t *sem)当调用职分完结使用这些命名非确定性信号量时,能够调用此接口。sem_close()会自由系统为那一个命名的复信号量分配的其他系统财富。若无应用sem_unlink()来删除复信号量,那么sem_close()对点名的时限信号量未有影响,可是,当钦点的时域信号量被全然排除链接时,信号量将要结尾三个职分关闭它时熄灭。必需小心幸免删除另三个调用义务已经锁定的非功率信号量。

  • int sem_unlink(const char *name)以此函数将去除由输入名参数命名的非时域信号量,如若有一个或八个职分正在使用连续信号量时调用sem_unlink(),复信号量的绝迹会被推移,直到全体引用都被调用sem_close()为止。

  • int sem_wait(sem_t *sem)尝试去锁住非确定性信号量sem,如果sem连续信号量已经被锁住了,调用该接口的Task不会回到,直到它成功的拿走锁,可能调用被时域信号中断。

  • int sem_timedwait(sem_t *sem, const struct timespec *abstime)以此函数类似于sem_wait(),分歧的是,当未有别的线程通过sem_post()来刑释模拟信号量的话,那么在指定时间超时过期时,这几个等待将会终止。

  • int sem_trywait(sem_t *sem)该函数仅在近期实信号量未锁定的事态下锁定钦定的时域信号量,无论怎么着,调用重返时不会卡住。

  • int sem_post(sem_t *sem)当二个义务使用完三个随机信号量时,将调用sem_post(),该函数会解锁频域信号量。假设该该操作发生的时限信号量值为正数,则不会堵塞等待数字信号量解锁的任务,随机信号量的值只是简短的递增。如若该操作发生的实信号量值为0,那么在堵塞的天职业中学,等待非数字信号量的职分将被允许从sem_wait()调用中中标再次来到。注意:能够从当中断管理程序中调用sem_post()

  • int sem_getvalue(sem_t *sem, int *sval)该函数用于获取时域信号量的值,当非确定性信号量被锁住时,获得的值要么为0,要么为负数,其绝对值表示等待非确定性信号量的职责数。

  • int sem_getprotocol(FAR const pthread_mutexattr_t *attr, FAR int *protocol)赢得功率信号量合同属性值,值有: SEM_PRIO_NONE, SEM_PRIO_INHERIT, SEM_PRIO_PROTECT

  • int sem_setprotocol(FAR pthread_mutexattr_t *attr, int protocol)设置能量信号量合同属性,值有: SEM_PRIO_NONE, SEM_PRIO_INHERIT, SEM_PRIO_PROTECTSEM_PRIO_INHERIT只有在CONFIG_PRIORITY_INHERITANCE被入选时才支撑,其它,SEM_PRIO_PROTECT在当前的配备下不辅助。

  • int work_usrstart:运维客户情势下的做事行列。
  • int work_queue(int qid, FAR struct work_s *work, worker_t worker, FAR void *arg, systime_t delay):将义务增加到职业行列中,义务将会在劳作行列中的线程上延缓运营。
  • int work_cancel(int qid, FAR struct work_s *work):将事先入列的职责删除掉。
  • int work_signal:通过专门的职业行列中的线程去施行义务管理。
  • work_available:检查职分的结构体是或不是可用。
  • void lpwork_boostpriority(uint8_t reqprio):进步线程实施的优先级。
  • void lpwork_restorepriority(uint8_t reqprio):苏醒线程执行的先行级。代码表明全数:
ssize_t mq_receive(mqd_t mqdes, void *msg, size_t msglen, int *prio);

下边将各自介绍上面讲到的文本,宗旨是环绕Makefile.unix文件。

整个.config文本内容格式如下所示,用来定义配置选项,在编写翻译时索要用到。

本文由mg4155com发布于mg4155线路检测手机版,转载请注明出处:Nuttx消息队列机制,从零开首邮件服务器搭建

关键词:

上一篇:没有了

下一篇:没有了