C# DateTime 日期格式化

在C#中DateTime是一个包含日期、时间的类型,此类型通过ToString()转换为字符串时,可根据传入给Tostring()的参数转换为多种字符串格式。

目录

1. 分类

2. 制式类型

3. 自定义格式类型 

1. 分类

DateTime调用ToString()传入的参数可分为制式和自定义两种:

1) 制式:系统自带的,转入特定的单个字符就可转换为系统已设定好的格式。

2) 自定义:自由组合日期代码(y、M、d、h、m、s、f)来展示丰富的日期格式。

2. 制式类型

说明:转入特定的单个字符就可转换为系统已设定好的格式。

2.1 格式来源

在Windows系统中的区域和语言(位置:控制面板 → 区域和语言)选项中可设置日期和时间的格式。

可设置的分类有:短日期、长日期、短时间、长时间等。

调用ToString()进行转换时,许多转换方式都是通过上面的4个分类进行组合。

2.2 符号对照表

2.2.1 环境

.net版本:4.0

系统版本:Win7

格式信息

2.2.2 对照表

符号 语法 示例(2016-05-09 13:09:55:2350) 格式说明
y DateTime.Now.ToString() 2016/5/9 13:09:55 短日期 长时间
d DateTime.Now.ToString("d") 2016/5/9 短日期
D DateTime.Now.ToString("D") 2016年5月9日 长日期
f DateTime.Now.ToString("f") 2016年5月9日 13:09 长日期 短时间
F DateTime.Now.ToString("F") 2016年5月9日 13:09:55 长日期 长时间
g DateTime.Now.ToString("g") 2016/5/9 13:09 短日期 短时间
G DateTime.Now.ToString("G")  2016/5/9 13:09:55 短日期 长时间
t DateTime.Now.ToString("t") 13:09 短时间
T DateTime.Now.ToString("T") 13:09:55 长时间
u DateTime.Now.ToString("u") 2016-05-09 13:09:55Z  
U DateTime.Now.ToString("U") 2016年5月9日 5:09:55 本初子午线的长日期和长时间
m DateTime.Now.ToString("m") 5月9日  
M DateTime.Now.ToString("M") 5月9日  
r DateTime.Now.ToString("r") Mon, 09 May 2016 13:09:55 GMT  
R DateTime.Now.ToString("R") Mon, 09 May 2016 13:09:55 GMT  
y DateTime.Now.ToString("y") 2016年5月  
Y DateTime.Now.ToString("Y") 2016年5月  
o DateTime.Now.ToString("o") 2016-05-09T13:09:55.2350000  
O DateTime.Now.ToString("O") 2016-05-09T13:09:55.2350000         
s DateTime.Now.ToString("s") 2016-05-09T13:09:55  

2.3 示例图

2.4 win2003版本 

在Win2003默认中的无字符、d、g、G格式中会用'-'符号替代'/'符号(短日期格式为:yyyy-m-d)。

3. 自定义格式类型

开发人员可通过英文字符(y、M、d、h、m、s、f) 分别代替(年、月、日、时、分、秒、毫秒)来自由组合日期时间格式。

3.1 符号对照表

.net版本:4.0

系统版本:Win7

符号 说明
语法 示例(2016-05-09 13:09:55:2350)
yy年份后两位DateTime.Now.ToString("yy")DateTime.Now.ToString("yy"); // => 16
yyyy4位年份DateTime.Now.ToString("yyyy")DateTime.Now.ToString("yyyy"); // => 2016
MM两位月份;单数月份前面用0填充DateTime.Now.ToString("MM")DateTime.Now.ToString("MM"); // => 05
dd日数DateTime.Now.ToString("dd")DateTime.Now.ToString("dd"); // => 09
ddd周几DateTime.Now.ToString("ddd")DateTime.Now.ToString("ddd"); // => 周一
dddd星期几DateTime.Now.ToString("dddd")DateTime.Now.ToString("dddd"); // => 星期一
hh12小时制的小时数DateTime.Now.ToString("hh") DateTime.Now.ToString("hh"); // => 01
HH24小时制的小时数DateTime.Now.ToString("HH")DateTime.Now.ToString("HH"); // => 13
mm分钟数DateTime.Now.ToString("mm")DateTime.Now.ToString("mm"); // => 09
ss秒数DateTime.Now.ToString("ss")DateTime.Now.ToString("ss"); // => 55
ff毫秒数前2位DateTime.Now.ToString("ff")DateTime.Now.ToString("ff"); // => 23
fff毫秒数前3位DateTime.Now.ToString("fff")DateTime.Now.ToString("fff"); // => 235
ffff毫秒数前4位DateTime.Now.ToString("ffff")DateTime.Now.ToString("ffff"); // => 2350
分隔符
可使用分隔符来分隔年月日时分秒。 包含的值可为:-、/、:等非关键字符 DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff"); // => 2016-05-09 13:09:55:2350 DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:ffff"); // => 2016/05/09 13:09:55:2350 DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:ffff dddd"); // => 2016/05/09 13:09:55:2350 星期一

3.2 示例图

.

.

windows 定时清理指定目录文件bat

eg:

删除E:\original目录下(包括子目录)所有以.png为后缀的、最后修改时间为7天前的文件

指令:

 forfiles /p E:\original /s /m *.png -d -7 /c "cmd /c del /q /f @path"

解释:

/p - 指定的路径
/s - 包括子目录
/m - 查找的文件名,支持通配符*。
/d - 指定日期,有绝对日期和相对日期, 此处-7指当前日期 的7天前

/c - 运行的命令行 表示为每个文件执行的命令。命令字符串应该
用双引号括起来。

                    默认命令是 "cmd /c echo @file"。下列变量
                    可以用在命令字符串中:
                    @file    - 返回文件名。
                    @fname   - 返回不带扩展名的文件名。
                    @ext     - 只返回文件的扩展。
                    @path    - 返回文件的完整路径。
                    @relpath - 返回文件的相对路径。
                    @isdir   - 如果文件类型是目录,返回 "TRUE";
                               如果是文件,返回 "FALSE"。
                    @fsize   - 以字节为单位返回文件大小。
                    @fdate   - 返回文件上一次修改的日期。
                    @ftime   - 返回文件上一次修改的时间。

版权声明:本文为CSDN博主「pokefade」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_19983129/article/details/73127547

mysql中的utf8mb4、utf8mb4_unicode_ci、utf8mb4_general_ci

1.utf8与utf8mb4(utf8 most bytes 4)

  • MySQL 5.5.3之后增加了utfmb4字符编码
  • 支持BMP(Basic Multilingual Plane,基本多文种平面)和补充字符
  • 最多使用四个字节存储字符

utf8mb4是utf8的超集并完全兼容utf8,能够用四个字节存储更多的字符。

标准的UTF-8字符集编码是可以使用1-4个字节去编码21位字符,这几乎包含了世界上所有能看见的语言。
MySQL里面实现的utf8最长使用3个字符,包含了大多数字符但并不是所有。例如emoji和一些不常用的汉字,如“墅”,这些需要四个字节才能编码的就不支持。

2.字符集、连接字符集、排序字符集

utf8mb4对应的排序字符集有utf8mb4_unicode_ci、utf8mb4_general_ci.

utf8mb4_unicode_ci和utf8mb4_general_ci的对比:

  • 准确性:
    • utf8mb4_unicode_ci是基于标准的Unicode来排序和比较,能够在各种语言之间精确排序
    • utf8mb4_general_ci没有实现Unicode排序规则,在遇到某些特殊语言或者字符集,排序结果可能不一致。
    • 但是,在绝大多数情况下,这些特殊字符的顺序并不需要那么精确。
  • 性能
    • utf8mb4_general_ci在比较和排序的时候更快
    • utf8mb4_unicode_ci在特殊情况下,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。
    • 但是在绝大多数情况下发,不会发生此类复杂比较。相比选择哪一种collation,使用者更应该关心字符集与排序规则在db里需要统一。

作者:AmyZYX
出处:http://www.cnblogs.com/amyzhu/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

================================================================

UTF-8是使用1~4个字节,一种变长的编码格式,字符编码。mb4即 most bytes 4,使用4个字节来表示完整的UTF-8。

mysql的 utf8 编码最大字符长度为 3 字节,如果遇到 4 字节的宽字符就会插入异常了。三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xffff,也就是 Unicode 中的基本多文种平面(BMP)。也就是说,任何不在基本多文本平面的 Unicode字符,都无法使用 Mysql 的 utf8 字符集存储。包括 Emoji 表情(Emoji 是一种特殊的 Unicode 编码,常见于 ios 和 android 手机上),和很多不常用的汉字,以及任何新增的 Unicode 字符等等。

总结:MySQL的utf8是utfmb3,只有三个字节,节省空间但不能表达全部的UTF-8。所以推荐使用utf8mb4。

utf8mb4_bin:将字符串每个字符用二进制数据编译存储,区分大小写,而且可以存二进制的内容。

utf8mb4_general_ci:ci即case insensitive,不区分大小写。没有实现Unicode排序规则,在遇到某些特殊语言或者字符集,排序结果可能不一致。但是,在绝大多数情况下,这些特殊字符的顺序并不需要那么精确。

utf8mb4_unicode_ci:是基于标准的Unicode来排序和比较,能够在各种语言之间精确排序,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。

utf8mb4_general_ci是一个遗留的 校对规则,不支持扩展,它仅能够在字符之间进行逐个比较。utf8_general_ci校对规则进行的比较速度很快,但是与使用 utf8mb4_unicode_ci的校对规则相比,比较正确性较差。

总结:general_ci 更快,unicode_ci 更准确。但相比现在的CPU来说,它远远不足以成为考虑性能的因素,索引涉及、SQL设计才是。使用者更应该关心字符集与排序规则在db里需要统一。

版权声明:本文为CSDN博主「yzh_1346983557」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yzh_1346983557/article/details/89643071

===================================================================

.

C++ / C# 数据类型对照

C++ 输入输出    C# 
==================================
char chr[255]   O    StringBuilder
KCA_DIR            I    int
LPCSTR             I    string
int                        I    int
LPSTR              O    StringBuilder
int*                      O    out int
DWORD              I    int
DWORD*          O    out int
BOOL                 I    bool
Rc_DBMgr          I    IntPtr
long*                  O    out long
API与C#的数据类型对应关系表
API数据类型类型描述C#类型API数据类型类型描述C#类型
WORD16位无符号整数ushortCHAR字符char
LONG32位无符号整数intDWORDLONG64位长整数long
DWORD32位无符号整数uintHDC设备描述表句柄int
HANDLE句柄,32位整数intHGDIOBJGDI对象句柄int
UINT32位无符号整数uintHINSTANCE实例句柄int
BOOL32位布尔型整数boolHWM窗口句柄int
LPSTR指向字符的32位指针stringHPARAM32位消息参数int
LPCSTR指向常字符的32位指针StringLPARAM32位消息参数int
BYTE字节byteWPARAM32位消息参数int
Wtypes.h 中的非托管类型 非托管 C 语言类型 托管类名 说明
HANDLE void* System.IntPtr 32 位
BYTE unsigned char System.Byte 8 位
SHORT short System.Int16 16 位
WORD unsigned short System.UInt16 16 位
INT int System.Int32 32 位
UINT unsigned int System.UInt32 32 位
LONG long System.Int32 32 位
BOOL long System.Int32 32 位
DWORD unsigned long System.UInt32 32 位
ULONG unsigned long System.UInt32 32 位
CHAR char System.Char 用 ANSI 修饰。
LPSTR char* System.String 或System.StringBuilder 用 ANSI 修饰。
LPCSTR Const char* System.String 或System.StringBuilder 用 ANSI 修饰。
LPWSTR wchar_t* System.String 或System.StringBuilder 用 Unicode 修饰。
LPCWSTR Const wchar_t* System.String 或System.StringBuilder 用 Unicode 修饰。
FLOAT Float System.Single 32 位
DOUBLE Double System.Double 64 位

STDINT.H

typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef signed __INT64 int64_t;

/* exact-width unsigned integer types */
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned __INT64 uint64_t;

/* 7.18.1.2 / / smallest type of at least n bits
/ / minimum-width signed integer types */
typedef signed char int_least8_t;
typedef signed short int int_least16_t;
typedef signed int int_least32_t;
typedef signed __INT64 int_least64_t;

/* minimum-width unsigned integer types */
typedef unsigned char uint_least8_t;
typedef unsigned short int uint_least16_t;
typedef unsigned int uint_least32_t;
typedef unsigned __INT64 uint_least64_t;

/* 7.18.1.3 / / fastest minimum-width signed integer types */
typedef signed int int_fast8_t;
typedef signed int int_fast16_t;
typedef signed int int_fast32_t;
typedef signed __INT64 int_fast64_t;

/* fastest minimum-width unsigned integer types */
typedef unsigned int uint_fast8_t;
typedef unsigned int uint_fast16_t;
typedef unsigned int uint_fast32_t;
typedef unsigned __INT64 uint_fast64_t;

typedef signed __INT64 intptr_t;
typedef unsigned __INT64 uintptr_t;

.

C# 调用C++DLL传递指向指针的指针参数的方法

C++结构体定义:

struct DeviceInfo
{    
    char szDeviceName[DEVICE_NAME_LEN];
    char szMACAddress[MAC_ADDRESS_LEN];        
    char szDeviceIP[DEVICE_IP_LEN];
};

C#结构体的定义:

[StructLayout(LayoutKind.Sequential)]
public struct DeviceInfo
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
    public string szDeviceName;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)]
    public string szMACAddress;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
    public string szDeviceIP; 


}

情况1:C++的dll负责分配内存

C++导出函数的声明

#define DLL_API  extern "C"  __declspec(dllexport)
DLL_API int findAllDevices(DeviceInfo** ppDeviceInfoList,int * pCount);

C#导入函数的声明

[DllImport("IPAlter_d.dll")]
public extern static int findAllDevices(out IntPtr pDeviceInfo, ref int pCount);

C#的调用方法:

IntPtr pBuff = new IntPtr();//直接new一个参数即可
 if (IPAlter.findAllDevices(out pBuff, ref cout) != 1)
 {
     System.Console.WriteLine("搜索失败!");
     System.Console.ReadLine();
     return;
 }
 for (int i = 0; i < cout; i++)
 {
IntPtr pPonitor = new IntPtr(pBuff.ToInt64() + Marshal.SizeOf(typeof(DeviceInfo)) * i);

System.Console.WriteLine(((DeviceInfo)Marshal.PtrToStructure(pPonitor, typeof(DeviceInfo))).szDeviceName); 
 System.Console.WriteLine(((DeviceInfo)Marshal.PtrToStructure(pPonitor, typeof(DeviceInfo))).szDeviceIP); 
 System.Console.WriteLine(((DeviceInfo)Marshal.PtrToStructure(pPonitor, typeof(DeviceInfo))).szMACAddress);
 
 }

情况2:C#负责分配内存

C++导出函数的声明:

DLL_API int findAllDevice(DeviceInfo* ppDeviceInfoList,int * pCount);

 C#导入函数的声明:

[DllImport("IPAlter_d.dll")]
public extern static int findAllDevice(IntPtr pDeviceInfo, ref int pCount);

 C#的调用方法:

DeviceInfo[] DeviceInfoList = new DeviceInfo[50];
 int size = Marshal.SizeOf(typeof(DeviceInfo)) * 50;
 byte[] bytes = new byte[size];
 IntPtr pBuff = Marshal.AllocHGlobal(size);
 if (IPAlter.findAllDevice(pBuff, ref cout) != 1)
 {
     System.Console.WriteLine("搜索失败!");
     System.Console.ReadLine();
     return;
 }
 for (int i = 0; i < cout; i++)
 {

IntPtr pPonitor = new IntPtr(pBuff.ToInt64() + Marshal.SizeOf(typeof(DeviceInfo)) * i);
 DeviceInfoList[i] = (DeviceInfo)Marshal.PtrToStructure(pPonitor, typeof(DeviceInfo));
 System.Console.WriteLine(DeviceInfoList[i].szDeviceName);
 System.Console.WriteLine(DeviceInfoList[i].szDeviceIP);
 System.Console.WriteLine(DeviceInfoList[i].szMACAddress);


 }
 Marshal.FreeHGlobal(pBuff);

可以参考:

http://www.cnblogs.com/cxwx/archive/2010/12/29/1921140.html

http://hi.baidu.com/fanr520/item/e761f9ca0766d462f6c95d55

http://blog.csdn.net/wangweitingaabbcc/article/details/7663949

C#调用C/C++ DLL方式

1、编写一个简单的DLL

设置为导出函数,并采用C风格。函数前加extern "C" __declspec(dllexport)。定义函数在退出前自己清空堆栈,在函数前加__stdcall。

新建一个头文件,在头文件中:

/* 加入任意你想加入的函数定义*/

extern "C" _declspec(dllexport) int _stdcall add(int *x,int *y); // 声明为C编译、链接方式的外部函数
extern "C" _declspec(dllexport) int _stdcall sub(int x,int y); // 声明为C编译、链接方式的外部函数

新建一个.cpp文件

#include "mydll.h"//貌似这两个头文件的顺序不能颠倒。我试了很多次,但是不能确定。

int add(int *x,int *y)//是否可以理解为,VS2010已经默认是 _stdcall,所以函数不用添加该修饰符
{
return *x+*y;
}

int sub(int x,int y)
{
return x-y;
}

把导出函数名称变为标准名称,需加模块定义文件,就是.def文件。

内容如下:(需要注释,前面加分号就可以了,注释需要单独行)

LIBRARY "TEST"

     EXPORTS

          ;add函数

          add

   ;sub函数

         sub

LIBRARY 库名称

EXPORTS 需要导出的各个函数名称

     重新编译之后,再用Depends工具看一下,函数已经变成标准add。这个在动态加载时很有用,特别是在GetProcAddress函数寻找入库函数的时候。

2、静态调用

新建一个C#的控制台项目,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;//添加

namespace mytest
{
  class Program
  {
    //----------------------------------------------------------------------------------------------
    [DllImport("mydll.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
    extern static int add(ref int a, ref int b);

    [DllImport("mydll.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
    extern static int sub(int a, int b);
    //--------------------------------------------------------------------------------------------------

    static void Main(string[] args)
    {

      int a, b,c,d;
      a = 1;
      b = 2;
      c=d= 0;

      Console.WriteLine(add(ref a,ref b).ToString());
      Console.WriteLine(sub(b,a).ToString());
      Console.Read();
    }
  }
}

 3、动态调用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;//添加

namespace mytest
{
  class Program
  {

[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(String path);//path 就是dll路径 返回结果为0表示失败。
[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);//lib是LoadLibrary返回的句柄,funcName 是函数名称 返回结果为0标识失败。
[DllImport("kernel32.dll")]
private extern static bool FreeLibrary(IntPtr lib);

//声明委托
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
delegate int ADD(ref int x, ref int y);
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
delegate int SUB(int x, int y);

static void Main(string[] args)
{

string dllPath = "G:\\VS2010软件学习\\c#调用C_dll\\mytest\\mytest\\mydll.dll";
string apiName1 = "add";
string apiName2 = "sub";
//使用动态加载

IntPtr hLib = LoadLibrary(dllPath);//加载函数

IntPtr apiFunction1 = GetProcAddress(hLib, apiName1);//获取函数地址
IntPtr apiFunction2 = GetProcAddress(hLib, apiName2);//获取函数地址

int i = Marshal.GetLastWin32Error();
if (apiFunction1.ToInt32() == 0)//0表示函数没找到
return;
if (apiFunction2.ToInt32() == 0)//0表示函数没找到
return;

//获取函数接口,相当于函数指针
ADD add1 = (Delegate)Marshal.GetDelegateForFunctionPointer(apiFunction1, typeof(ADD)) as ADD;
SUB sub1 = (SUB)Marshal.GetDelegateForFunctionPointer(apiFunction2, typeof(SUB));

// //调用函数
int a, b,c;
a = 1;
b = 2;
c= 0;
//add1(ref a,ref b);
c=sub1(b,a);
// //释放句柄

FreeLibrary(hLib );

Console.WriteLine(c.ToString());
//Console.WriteLine(add(ref a,ref b).ToString());
//Console.WriteLine(sub(10,2).ToString());
Console.Read();

}

  }
}

注意:

C#时常需要调用C/C++DLL,当传递参数时时常遇到问题,尤其是传递和返回字符串时。VC++中主要字符串类型为:LPSTR,LPCSTR, LPCTSTR, string, CString, LPCWSTR, LPWSTR等,但转为C#类型却不完全相同。

类型对照:

C/C++----------C#

BSTR ---------  StringBuilder

LPCTSTR --------- StringBuilder

LPCWSTR ---------  IntPtr

handle---------IntPtr

hwnd-----------IntPtr

char *----------string

int * -----------ref int

int &-----------ref int

void *----------IntPtr

unsigned char *-----ref byte

Struct需要在C#里重新定义一个Struct

CallBack回调函数需要封装在一个委托里,delegate static extern int FunCallBack(string str);

注意在每个函数的前面加上public static extern +返回的数据类型,如果不加public ,函数默认为私有函数,调用就会出错。

在C#调用C++ DLL封装库时会出现两个问题:

1. 数据类型转换问题 
2. 指针或地址参数传送问题

Application Path

// 获取程序的基目录。
System.AppDomain.CurrentDomain.BaseDirectory

// 获取模块的完整路径。
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName

// 获取和设置当前目录(该进程从中启动的目录)的完全限定目录。
System.Environment.CurrentDirectory

// 获取应用程序的当前工作目录。
System.IO.Directory.GetCurrentDirectory()

// 获取和设置包括该应用程序的目录的名称。
System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase

// 获取启动了应用程序的可执行文件的路径。
System.Windows.Forms.Application.StartupPath

// 获取启动了应用程序的可执行文件的路径及文件名
System.Windows.Forms.Application.ExecutablePath

AppDomain.CurrentDomain.BaseDirectory 返回结果为: D:\mycode\
Application.StartupPath 返回结果为: D:\mycode

.

.

串口、COM口、TTL、RS232、RS485

1、串口、COM口是指的物理接口形式(硬件)。而TTL、RS-232、RS-485是指的电平标准(电信号)。

2、接设备的时候,一般只接GND RX TX。不会接Vcc或者+3.3v的电源线,避免与目标设备上的供电冲突。

3、PL2303、CP2102芯片都是常用的USB转TTL串口的芯片,用USB来扩展串口(TTL电平)。

4、MAX232芯片是TTL电平与RS232电平的专用双向转换芯片,可以TTL转RS-232,也可以RS-232转TTL。

5、TTL标准是低电平为0,高电平为1(+5V电平)。RS-232标准是正电平为0,负电平为1(±15V电平)。

6、RS-485的电气特性:逻辑“1”以两线间的电压差为+(2—6)V表示;逻辑“0”以两线间的电压差为-(2—6)V表示。接口信号电平比RS-232-C降低了,就不易损坏接口电路的芯片,且该电平与TTL电平兼容,可方便与TTL电路连接。

    串口、COM口

    COM口即串行通讯端口,简称串口。一般我们见到的是两种物理标准。D型9针插头,和 4针杜邦头两种。下图是个USB转TTL串口的小板,可以用USB扩展出一个串口。对于使用笔记本或者没有COM的台机开发的嵌入式工程师来说就是必备工具。除了可以使用串口给MCU下载程序外,还是辅助调试程序的神器。

    RS232

上边介绍的都是USB转TTL串口,如果目标设备上是RS-232串口(D型9针接口)可咋整呀?再接一片MAX232转换一下就行,如下图。

    RS485

    在要求通信距离为几十米到上千米时,广泛采用RS-485串行总线标准。RS-485采用平衡发送和差分接收,因此具有抑制共模干扰的能力。RS-485接口的最大传输距离标准值为4000英尺(约1219米),实际上可达3000米,另外RS-232-C接口在总线上只允许连接1个收发器,即单站能力。而RS-485接口在总线上是允许连接多达128个收发器。

.

centos 7

timedatectl

timedatectl list-timezones | grep Asia
timedatectl set-timezone Asia/Shanghai

timedatectl list-timezones | grep UTC
timedatectl set-timezone UTC

; NTP
timedatectl set-ntp true
; timedatectl set-local-rtc true

systemctl status chrony
vi /etc/chrony.conf

hostname
hostnamectl --static set-hostname host-331582

vi /etc/selinux/config
echo 'SELINUX=disabled' >> /etc/selinux/config
echo '' >> /etc/selinux/config

.

Linux dd

一、dd命令的解释

dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。

注意:指定数字的地方若以下列字符结尾,则乘以相应的数字:b=512;c=1;k=1024;w=2

参数注释:

1. if=文件名:输入文件名,缺省为标准输入。即指定源文件。< if=input file >

2. of=文件名:输出文件名,缺省为标准输出。即指定目的文件。< of=output file >

3. ibs=bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节。

    obs=bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节。

    bs=bytes:同时设置读入/输出的块大小为bytes个字节。

4. cbs=bytes:一次转换bytes个字节,即指定转换缓冲区大小。

5. skip=blocks:从输入文件开头跳过blocks个块后再开始复制。

6. seek=blocks:从输出文件开头跳过blocks个块后再开始复制。

注意:通常只用当输出文件是磁盘或磁带时才有效,即备份到磁盘或磁带时才有效。

7. count=blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数。

8. conv=conversion:用指定的参数转换文件。

    ascii:转换ebcdic为ascii

     ebcdic:转换ascii为ebcdic

    ibm:转换ascii为alternate ebcdic

    block:把每一行转换为长度为cbs,不足部分用空格填充

    unblock:使每一行的长度都为cbs,不足部分用空格填充

    lcase:把大写字符转换为小写字符

    ucase:把小写字符转换为大写字符

    swab:交换输入的每对字节

     noerror:出错时不停止

     notrunc:不截短输出文件

    sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。

二、dd应用实例

1.将本地的/dev/hdb整盘备份到/dev/hdd

#dd if=/dev/hdb of=/dev/hdd

2./dev/hdb全盘数据备份到指定路径的image文件

#dd if=/dev/hdb of=/root/image

3.将备份文件恢复到指定盘

#dd if=/root/image of=/dev/hdb

4.备份/dev/hdb全盘数据,并利用gzip工具进行压缩,保存到指定路径

#dd if=/dev/hdb | gzip > /root/image.gz

5.将压缩的备份文件恢复到指定盘

#gzip -dc /root/image.gz | dd of=/dev/hdb

6.备份与恢复MBR

备份磁盘开始的512个字节大小的MBR信息到指定文件:

#dd if=/dev/hda of=/root/image count=1 bs=512

   count=1指仅拷贝一个块;bs=512指块大小为512个字节。

恢复:

#dd if=/root/image of=/dev/had

将备份的MBR信息写到磁盘开始部分

7.备份软盘

#dd if=/dev/fd0 of=disk.img count=1 bs=1440k (即块大小为1.44M)

8.拷贝内存内容到硬盘

#dd if=/dev/mem of=/root/mem.bin bs=1024 (指定块大小为1k)  

9.拷贝光盘内容到指定文件夹,并保存为cd.iso文件

#dd if=/dev/cdrom(hdc) of=/root/cd.iso

10.增加swap分区文件大小

第一步:创建一个大小为256M的文件:

#dd if=/dev/zero of=/swapfile bs=1024 count=262144

第二步:把这个文件变成swap文件:

#mkswap /swapfile

第三步:启用这个swap文件:

#swapon /swapfile

第四步:编辑/etc/fstab文件,使在每次开机时自动加载swap文件:

/swapfile    swap    swap    default   0 0

11.销毁磁盘数据

#dd if=/dev/urandom of=/dev/hda1

注意:利用随机的数据填充硬盘,在某些必要的场合可以用来销毁数据。

12.测试硬盘的读写速度

#dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file

#dd if=/root/1Gb.file bs=64k | dd of=/dev/null

通过以上两个命令输出的命令执行时间,可以计算出硬盘的读、写速度。

13.确定硬盘的最佳块大小:

#dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file

#dd if=/dev/zero bs=2048 count=500000 of=/root/1Gb.file

#dd if=/dev/zero bs=4096 count=250000 of=/root/1Gb.file

#dd if=/dev/zero bs=8192 count=125000 of=/root/1Gb.file

通过比较以上命令输出中所显示的命令执行时间,即可确定系统最佳的块大小。

14.修复硬盘:

#dd if=/dev/sda of=/dev/sda 或dd if=/dev/hda of=/dev/hda

当硬盘较长时间(一年以上)放置不使用后,磁盘上会产生magnetic flux point,当磁头读到这些区域时会遇到困难,并可能导致I/O错误。当这种情况影响到硬盘的第一个扇区时,可能导致硬盘报废。上边的命令有可能使这些数 据起死回生。并且这个过程是安全、高效的。

15.利用netcat远程备份

#dd if=/dev/hda bs=16065b | netcat < targethost-IP > 1234

在源主机上执行此命令备份/dev/hda

#netcat -l -p 1234 | dd of=/dev/hdc bs=16065b

在目的主机上执行此命令来接收数据并写入/dev/hdc

#netcat -l -p 1234 | bzip2 > partition.img

#netcat -l -p 1234 | gzip > partition.img

以上两条指令是目的主机指令的变化分别采用bzip2、gzip对数据进行压缩,并将备份文件保存在当前目录。

16.将一个大视频文件的第i个字节的值改成0x41(大写字母AASCII值)

#echo A | dd of=bigfile seek=$i bs=1 count=1 conv=notrunc

17.建立linux虚拟盘,用文件模拟磁盘

在进行linux的实验中,如果没有多余的硬盘来做测试。则可以在linux下使用文件来模拟磁盘,以供测试目的。

其模拟过程如下所示,摘录自《Oracle数据库核心技术与实务详解-教你如何成为Oracle 10g OCP》一书。

1)以root用户创建一个ASM磁盘所在的目录。

# mkdir –p /u01/asmdisks

2)通过dd命令创建6个400M大小的文件,每个文件代表一块磁盘。

[root@book u01]

# cd asmdisks

[root@book asmdisks]

# dd if=/dev/zero of=asm_disk1 bs=1024k count=400

[root@book asmdisks]

# dd if=/dev/zero of=asm_disk2 bs=1024k count=400

[root@book asmdisks]

# dd if=/dev/zero of=asm_disk3 bs=1024k count=400

[root@book asmdisks]

# dd if=/dev/zero of=asm_disk4 bs=1024k count=400

[root@book asmdisks]

# dd if=/dev/zero of=asm_disk5 bs=1024k count=400

[root@book asmdisks]

# dd if=/dev/zero of=asm_disk6 bs=1024k count=400

3)将这些文件与裸设备关联。

[root@book asmdisks]

# chmod 777 asm_disk*

[root@book asmdisks]

# losetup /dev/loop1 asm_disk1

[root@book asmdisks]

# losetup /dev/loop2 asm_disk2

[root@book asmdisks]

# losetup /dev/loop3 asm_disk3

[root@book asmdisks]

# losetup /dev/loop4 asm_disk4

[root@book asmdisks]

# losetup /dev/loop5 asm_disk5

[root@book asmdisks]

# losetup /dev/loop6 asm_disk6

注意:如果要删除通过dd模拟出的虚拟磁盘文件的话,直接删除模拟出的磁盘文件

(也就是asm_disk1、asm_disk2…asm_disk6)还不够,还必须执行losetup -d /dev/loopN,在这里N从1到6。否则,磁盘文件所占用的磁盘空间不能释放

三、/dev/null和/dev/zero的区别

/dev/null,外号叫无底洞,你可以向它输出任何数据,它通吃,并且不会撑着!

/dev/zero,是一个输入设备,你可你用它来初始化文件。该设备无穷尽地提供0,可以使用任何你需要的数目——设备提供的要多的多。他可以用于向设备或文件写入字符串0。

/dev/null------它是空设备,也称为位桶(bit bucket)。任何写入它的输出都会被抛弃。如果不想让消息以标准输出显示或写入文件,那么可以将消息重定向到位桶。

#if=/dev/zero of=./test.txt bs=1k count=1
#ls –l

total 4
-rw-r--r--    1 oracle   dba          1024 Jul 15 16:56 test.txt

#find / -name access_log  2>/dev/null

3.1使用/dev/null 

把/dev/null看作"黑洞", 它等价于一个只写文件,所有写入它的内容都会永远丢失.,而尝试从它那儿读取内容则什么也读不到。然而, /dev/null对命令行和脚本都非常的有用

禁止标准输出

#cat $filename >/dev/null

文件内容丢失,而不会输出到标准输出.

禁止标准错误

#rm $badname 2>/dev/null

这样错误信息[标准错误]就被丢到太平洋去了

禁止标准输出和标准错误的输出

#cat $filename 2>/dev/null >/dev/null

如果"filename"不存在,将不会有任何错误信息提示;如果"

filename"存在, 文件的内容不会打印到标准输出。

因此,上面的代码根本不会输出任何信息。当只想测试命令的退出码而不想有任何输出时非常有用。

#cat $filename &>/dev/null

这样其实也可以, 由 Baris Cicek 指出

自动清空日志文件的内容

Deleting contents of a file, but preserving the file itself, with all attendant permissions (from Example 2-1 and Example 2-3): 

#cat /dev/null > /var/log/messages
#  : > /var/log/messages   有同样的效果, 但不会产生新的进程.(因为:是内建的)
#cat /dev/null > /var/log/wtmp

特别适合处理这些由商业Web站点发送的讨厌的"cookies"

隐藏cookie而不再使用

#if [ -f ~/.netscape/cookies ]  # 如果存在则删除.
#then
#rm -f ~/.netscape/cookies
#fi
#ln -s /dev/null ~/.netscape/cookies

现在所有的cookies都会丢入黑洞而不会保存在磁盘上了.

3.2使用/dev/zero

像/dev/null一样, /dev/zero也是一个伪文件, 但它实际上产生连续不断的null的流(二进制的零流,而不是ASCII型的)。 写入它的输出会丢失不见, 而从/dev/zero读出一连串的null也比较困难, 虽然这也能通过od或一个十六进制编辑器来做到。 /dev/zero主要的用处是用来创建一个指定长度用于初始化的空文件,就像临时交换文件

/dev/zero创建一个交换临时文件

#!/bin/bash

  # 创建一个交换文件.

  ROOT_UID=0 # Root 用户的 $UID 是 0.

  E_WRONG_USER=65 # 不是 root?

  FILE=/swap

  BLOCKSIZE=1024

  MINBLOCKS=40

  SUCCESS=0

  # 这个脚本必须用root来运行.

  if [ "UID"−ne"

ROOT_UID" ]

   then

   echo; echo "You must be root to run this script."; echo

   exit $E_WRONG_USER

  fi

  blocks={1:-

MINBLOCKS} # 如果命令行没有指定,

  #+ 则设置为默认的40块.

  # 上面这句等同如:

  # --------------------------------------------------

  # if [ -n "$1" ]

  # then

  # blocks=$1

  # else

  # blocks=$MINBLOCKS

  # fi

  # --------------------------------------------------

 if [ "blocks"−lt

MINBLOCKS ]

 then

 blocks=$MINBLOCKS # 最少要有 40 个块长.

 fi

 echo "Creating swap file of size $blocks blocks (KB)."

 dd if=/dev/zero of=FILEbs=

BLOCKSIZE count=$blocks # 把零写入文件.

 mkswap FILE

blocks # 将此文件建为交换文件(或称交换分区).

 swapon $FILE # 激活交换文件.

 echo "Swap file created and activated."

 exit $SUCCESS 

关于 /dev/zero 的另一个应用是为特定的目的而用零去填充一个指定大小的文件, 如挂载一个文件系统到环回设备 (loopback device)或"安全地" 删除一个文件

例子创建ramdisk

#!/bin/bash

 # ramdisk.sh

 # "ramdisk"是系统RAM内存的一段,

 #+ 它可以被当成是一个文件系统来操作.

 # 它的优点是存取速度非常快 (包括读和写).

 # 缺点: 易失性, 当计算机重启或关机时会丢失数据.

 #+ 会减少系统可用的RAM.

 # 10 # 那么ramdisk有什么作用呢?

 # 保存一个较大的数据集在ramdisk, 比如一张表或字典,

 #+ 这样可以加速数据查询, 因为在内存里查找比在磁盘里查找快得多.

  E_NON_ROOT_USER=70 # 必须用root来运行.

  ROOTUSER_NAME=root

  MOUNTPT=/mnt/ramdisk

  SIZE=2000 # 2K 个块 (可以合适的做修改)

  BLOCKSIZE=1024 # 每块有1K (1024 byte) 的大小

  DEVICE=/dev/ram0 # 第一个 ram 设备

  username=`id -nu`

  if [ "username"!="

ROOTUSER_NAME" ]

  then

    echo "Must be root to run \"`basename $0`\"."

    exit $E_NON_ROOT_USER

  fi

   if [ ! -d "$MOUNTPT" ] # 测试挂载点是否已经存在了,

  then #+ 如果这个脚本已经运行了好几次了就不会再建这个目录了

    mkdir $MOUNTPT #+ 因为前面已经建立了.

  fi

  dd if=/dev/zero of=DEVICEcount=

SIZE bs=$BLOCKSIZE

   # 把RAM设备的内容用零填充.                                              

   # 为何需要这么做?

  mke2fs $DEVICE # 在RAM设备上创建一个ext2文件系统.

  mount DEVICE

MOUNTPT # 挂载设备.

  chmod 777 $MOUNTPT # 使普通用户也可以存取这个ramdisk.

  # 但是, 只能由root来缷载它.

  echo "\"$MOUNTPT\" now available for use."

 # 现在 ramdisk 即使普通用户也可以用来存取文件了.

 # 注意, ramdisk是易失的, 所以当计算机系统重启或关机时ramdisk里的内容会消失.

 # 拷贝所有你想保存文件到一个常规的磁盘目录下.

 # 重启之后, 运行这个脚本再次建立起一个 ramdisk.

 # 仅重新加载 /mnt/ramdisk 而没有其他的步骤将不会正确工作.

 # 如果加以改进, 这个脚本可以放在 /etc/rc.d/rc.local,

 #+ 以使系统启动时能自动设立一个ramdisk.

 # 这样很合适速度要求高的数据库服务器.

 exit 0

Links:

https://www.cnblogs.com/jikexianfeng/p/6103500.html