当前位置: 首页 > news >正文

展览搭建设计网站广东阳江房产网

展览搭建设计网站,广东阳江房产网,网站和微信公众号建设,成都网络营销公司排名本章将会讨论如下主题内容。 ⚫ Linux 系统的文件类型#xff1b; ⚫ stat 系统调用#xff1b; ⚫ 文件各种属性介绍#xff1a;文件属主、访问权限、时间戳#xff1b; ⚫ 符号链接与硬链接#xff1b; ⚫ 目录#xff1b; ⚫ 删除文件与文件重命名。 一、Linux 系统中…本章将会讨论如下主题内容。 ⚫ Linux 系统的文件类型 ⚫ stat 系统调用 ⚫ 文件各种属性介绍文件属主、访问权限、时间戳 ⚫ 符号链接与硬链接 ⚫ 目录 ⚫ 删除文件与文件重命名。 一、Linux 系统中的文件类型 在 Linux 系统下可以通过 stat 命令或者 ls 命令来查看文件类型如下所示 其中第一个字符’ - ‘就用于表示文件的类型减号’ - 就表示该文件是一个普通文件看看其它文件类型使用什么字符表示 ⚫ ’ - 普通文件 ⚫ ’ d 目录文件 ⚫ ’ c 字符设备文件 ⚫ ’ b 块设备文件 ⚫ ’ l 符号链接文件 ⚫ ’ s 套接字文件 ⚫ ’ p 管道文件 二、stat 函数 Linux 下可以使用 stat 命令查看文件的属性其实这个命令内部就是通过调用 stat()函数来获取文件属性的stat 函数是 Linux 中的系统调用。 #include sys/types.h #include sys/stat.h #include unistd.h int stat(const char *pathname, struct stat *buf);pathname用于指定一个需要查看属性的文件路径。 bufstruct stat 类型指针用于指向一个 struct stat 结构体变量。调用 stat 函数的时候需要传入一个 struct stat 变量的指针获取到的文件属性信息就记录在struct stat结构体中。 返回值成功返回 0失败返回-1并设置 error。 1、struct stat 结构体 struct stat {dev_t st_dev; /* 文件所在设备的 ID */ino_t st_ino; /* 文件对应 inode 节点编号 */mode_t st_mode; /* 文件对应的模式 */nlink_t st_nlink; /* 文件的链接数 */uid_t st_uid; /* 文件所有者的用户 ID */gid_t st_gid; /* 文件所有者的组 ID */dev_t st_rdev; /* 设备号指针对设备文件 */off_t st_size; /* 文件大小以字节为单位 */blksize_t st_blksize; /* 文件内容存储的块大小 */blkcnt_t st_blocks; /* 文件内容所占块数 */struct timespec st_atim; /* 文件最后被访问的时间 */struct timespec st_mtim; /* 文件内容最后被修改的时间 */struct timespec st_ctim; /* 文件状态最后被改变的时间 */ };1.1、st_mode 变量 st_mode 是 structstat 结构体中的一个成员变量是一个 32 位无符号整形数据该变量记录了文件的类型、文件的权限这些信息其表示方法如下所示 在 mode 参数中表示权限的宏定义如下 S_IRWXU 00700 owner has read, write, and execute permission S_IRUSR 00400 owner has read permission S_IWUSR 00200 owner has write permission S_IXUSR 00100 owner has execute permission S_IRWXG 00070 group has read, write, and execute permission S_IRGRP 00040 group has read permission S_IWGRP 00020 group has write permission S_IXGRP 00010 group has execute permission S_IRWXO 00007 others (not in group) have read, write, and execute permission S_IROTH 00004 others have read permission S_IWOTH 00002 others have write permission S_IXOTH 00001 others have execute permission譬如判断文件所有者对该文件是否具有可执行权限可以通过以下方法测试假设 st 是 structstat 类型变量 if (st.st_mode S_IXUSR) {//有权限 } else {//无权限 }这里我们重点来看看“文件类型”这 4 个 bit 位这 4 个 bit 位用于描述该文件的类型譬如该文件是普通文件、还是链接文件、亦或者是一个目录等那么就可以通过这 4 个 bit 位数据判断出来如下所示 S_IFSOCK 0140000 socket套接字文件 S_IFLNK 0120000 symbolic link链接文件 S_IFREG 0100000 regular file普通文件 S_IFBLK 0060000 block device块设备文件 S_IFDIR 0040000 directory目录 S_IFCHR 0020000 character device字符设备文件 S_IFIFO 0010000 FIFO管道文件我们还可以使用 Linux 系统封装好的宏来进行判断如下所示m 是 st_mode 变量 S_ISREG(m) //判断是不是普通文件如果是返回 true否则返回 false S_ISDIR(m) //判断是不是目录如果是返回 true否则返回 false S_ISCHR(m) //判断是不是字符设备文件如果是返回 true否则返回 false S_ISBLK(m) //判断是不是块设备文件如果是返回 true否则返回 false S_ISFIFO(m) //判断是不是管道文件如果是返回 true否则返回 false S_ISLNK(m) //判断是不是链接文件如果是返回 true否则返回 falseS_ISSOCK(m) #判断是不是套接字文件如果是返回 true否则返回 false有了这些宏之后就可以通过如下方式来判断文件类型了 /* 判断是不是普通文件 */ if (S_ISREG(st.st_mode)) {/* 是 */ } /* 判断是不是目录 */ if (S_ISDIR(st.st_mode)) {/* 是 */ }2、struct timespec 结构体 struct timespec {time_t tv_sec; /* 秒 */syscall_slong_t tv_nsec; /* 纳秒 */ };编程实战练习 1 #include sys/types.h #include sys/stat.h #include unistd.h #include stdio.h #include stdlib.hint main(void) {struct stat file_stat;int ret;/* 获取文件属性 */ret stat(./test_file, file_stat);if (-1 ret) {perror(stat error);exit(-1);}/* 打印文件大小和 inode 编号 */printf(file size: %ld bytes\ninode number: %ld\n, file_stat.st_size,file_stat.st_ino);exit(0); }编程实战练习 2 #include sys/types.h #include sys/stat.h #include unistd.h #include stdio.h #include stdlib.hint main(void) {struct stat file_stat;int ret;/* 获取文件属性 */ret stat(./test_file, file_stat);if (-1 ret) {perror(stat error);exit(-1);}/* 判读文件类型 */switch (file_stat.st_mode S_IFMT) {case S_IFSOCK: printf(socket); break;case S_IFLNK: printf(symbolic link); break;case S_IFREG: printf(regular file); break;case S_IFBLK: printf(block device); break;case S_IFDIR: printf(directory); break;case S_IFCHR: printf(character device); break;case S_IFIFO: printf(FIFO); break;}printf(\n);/* 判断该文件对其它用户是否具有读权限 */if (file_stat.st_mode S_IROTH)printf(Read: Yes\n);elseprintf(Read: No\n);/* 判断该文件对其它用户是否具有写权限 */if (file_stat.st_mode S_IWOTH)printf(Write: Yes\n);elseprintf(Write: No\n);exit(0); }编程实战练习 3 #include sys/types.h #include sys/stat.h #include unistd.h #include stdio.h #include stdlib.h #include time.hint main(void) {struct stat file_stat;struct tm file_tm;char time_str[100];int ret;/* 获取文件属性 */ret stat(./test_file, file_stat);if (-1 ret) {perror(stat error);exit(-1);}/* 打印文件最后被访问的时间 */localtime_r(file_stat.st_atim.tv_sec, file_tm);strftime(time_str, sizeof(time_str), %Y-%m-%d %H:%M:%S, file_tm);printf(time of last access: %s\n, time_str);/* 打印文件内容最后被修改的时间 */localtime_r(file_stat.st_mtim.tv_sec, file_tm);strftime(time_str, sizeof(time_str), %Y-%m-%d %H:%M:%S, file_tm);printf(time of last modification: %s\n, time_str);/* 打印文件状态最后改变的时间 */localtime_r(file_stat.st_ctim.tv_sec, file_tm);strftime(time_str, sizeof(time_str), %Y-%m-%d %H:%M:%S, file_tm);printf(time of last status change: %s\n, time_str);exit(0); }三、fstat 和 lstat 函数 1、fstat 函数 fstat 与 stat 区别在于stat 是从文件名出发得到文件属性信息不需要先打开文件而 fstat 函数则是从文件描述符出发得到文件属性信息所以使用 fstat 函数之前需要先打开文件得到文件描述符。 2、lstat 函数 lstat()与 stat、fstat 的区别在于对于符号链接文件stat、fstat 查阅的是符号链接文件所指向的文件对应的文件属性信息而 lstat 查阅的是符号链接文件本身的属性信息。 #include sys/types.h #include sys/stat.h #include unistd.h int lstat(const char *pathname, struct stat *buf);四、文件属主 Linux 是一个多用户操作系统系统中一般存在着好几个不同的用户而 Linux 系统中的每一个文件都有一个与之相关联的用户和用户组通过这个信息可以判断文件的所有者和所属组。 文件所有者表示该文件属于“谁”也就是属于哪个用户。一般来说文件在创建时其所有者就是创建该文件的那个用户。譬如当前登录用户为 dt使用 touch 命令创建了一个文件那么这个文件的所有者就是 dt同理在程序中调用 open 函数创建新文件时也是如此执行该程序的用户是谁其文件所有者便是谁。 Linux系统通过用户 IDUID或组 IDGID就可以识别出不同的用户和用户组。 既然 Linux 下的每一个文件都有与之相关联的用户 ID 和组 ID那么对于一个进程来说亦是如此与一个进程相关联的 ID 有 5 个或更多如下表所示 ⚫ 实际用户 ID 和实际组 ID 标识我们究竟是谁也就是执行该进程的用户是谁、以及该用户对应的所属组实际用户 ID 和实际组 ID 确定了进程所属的用户和组。 ⚫ 进程的有效用户 ID、有效组 ID 以及附属组 ID 用于文件访问权限检查。 1、有效用户 ID 和有效组 ID 首先对于有效用户 ID 和有效组 ID 来说这是进程所持有的概念对于文件来说并无此属性有效用户 ID 和有效组 ID 是站在操作系统的角度用于给操作系统判断当前执行该进程的用户在当前环境下对某个文件是否拥有相应的权限。 在Linux系统中当进行权限检查时并不是通过进程的实际用户和实际组来参与权限检查的而是通过有效用户和有效组来参与文件权限检查。通常绝大部分情况下进程的有效用户等于实际用户有效用户 ID 等于实际用户 ID有效组等于实际组有效组 ID 等于实际组 ID。 2、chown 函数 chown 是一个系统调用该系统调用可用于改变文件的所有者用户 ID和所属组组 ID。其实在Linux 系统下也有一个 chown 命令该命令的作用也是用于改变文件的所有者和所属组譬如将 testApp.c文件的所有者和所属组修改为 root sudo chown root:root testApp.cchown 函数原型如下所示 #include unistd.h int chown(const char *pathname, uid_t owner, gid_t group);函数参数和返回值如下所示 pathname用于指定一个需要修改所有者和所属组的文件路径。 owner将文件的所有者修改为该参数指定的用户以用户 ID 的形式描述 group将文件的所属组修改为该参数指定的用户组以用户组 ID 的形式描述 返回值成功返回 0失败将返回-1兵并且会设置 errno。 测试 #include unistd.h #include stdio.h #include stdlib.hint main(void) {if (-1 chown(./test_file, 0, 0)) {perror(chown error);exit(-1);}exit(0); }在 Linux 系统下可以使用 getuid 和 getgid 两个系统调用分别用于获取当前进程的用户 ID 和用户组ID这里说的进程的用户 ID 和用户组 ID 指的就是进程的实际用户 ID 和实际组 ID这两个系统调用函数原型如下所示 #include unistd.h #include sys/types.huid_t getuid(void); gid_t getgid(void);#include unistd.h #include stdio.h #include stdlib.h int main(void) {printf(uid: %d\n, getuid());if (-1 chown(./test_file, 0, 0)) {perror(chown error);exit(-1);}exit(0); }很明显可以看到两次执行同一个应用程序它们的用户 ID 是不一样的因为加上了 sudo 使得应用程序的用户 ID 由原本的普通用户 ID 1000 变成了超级用户 ID 0使得该进程变成了超级用户进程所以调用chown 函数就不会报错。 3、fchown 和 lchown 函数 fchown()、lchown()这两个函数与 chown()的区别就像是 fstat()、lstat()与 stat 的区别。 五、文件访问权限 struct stat 结构体中的 st_mode 字段记录了文件的访问权限位。当提及到文件时指的是前面给大家介绍的任何类型的文件并不仅仅指的是普通文件所有文件类型目录、设备文件都有访问权限accesspermission可能有很多人认为只有普通文件才有访问权限这是一种误解 普通权限 譬如使用 ls 命令或 stat 命令可以查看到文件的这 9 个访问权限如下所示 而对于进程来说参与文件权限检查的是进程的有效用户、有效用户组以及进程的附属组用户。 如何判断权限首先要搞清楚该进程对于需要进行操作的文件来说是属于哪一类“角色” ⚫ 如果进程的有效用户 ID 等于文件所有者 IDst_uid意味着该进程以文件所有者的角色存在 ⚫ 如果进程的有效用户 ID 并不等于文件所有者 ID意味着该进程并不是文件所有者身份但是进程的有效用户组 ID 或进程的附属组 ID 之一等于文件的组 IDst_gid那么意味着该进程以文件所属组成员的角色存在也就是文件所属组的同组用户成员。 ⚫ 如果进程的有效用户 ID 不等于文件所有者 ID、并且进程的有效用户组 ID 或进程的所有附属组 ID均不等于文件的组 IDst_gid那么意味着该进程以其它用户的角色存在。 ⚫ 如果进程的有效用户 ID 等于 0root 用户则无需进行权限检查直接对该文件拥有最高权限。 特殊权限 从高位到低位依次表示文件的 set-user-ID 位权限、set-group-ID 位权限以及 sticky 位权限如下所示 1、检查文件权限 access #include unistd.h int access(const char *pathname, int mode);函数参数和返回值含义如下 pathname需要进行权限检查的文件路径。 mode该参数可以取以下值 ⚫ F_OK检查文件是否存在 ⚫ R_OK检查是否拥有读权限 ⚫ W_OK检查是否拥有写权限 ⚫ X_OK检查是否拥有执行权限 除了可以单独使用之外还可以通过按位或运算符 | 组合在一起。 返回值检查项通过则返回 0表示拥有相应的权限并且文件存在否则返回-1如果多个检查项组合在一起只要其中任何一项不通过都会返回-1。 2、修改文件权限 chmod #include sys/stat.h int chmod(const char *pathname, mode_t mode);函数参数及返回值如下所示 pathname需要进行权限修改的文件路径若该参数所指为符号链接实际改变权限的文件是符号链接所指向的文件而不是符号链接文件本身。 mode该参数用于描述文件权限与 open 函数的第三个参数一样这里不再重述可以直接使用八进制数据来描述也可以使用相应的权限宏单个或通过位或运算符 | 组合。 返回值成功返回 0失败返回-1并设置 errno。 文件权限对于文件来说是非常重要的属性是不能随随便便被任何用户所修改的要想更改文件权限要么是超级用户root进程、要么进程有效用户 ID 与文件的用户 ID文件所有者相匹配。 fchmod 函数 该函数功能与 chmod 一样参数略有不同。 六、符号链接软链接与硬链接 在 Linux 系统中有两种链接文件分为软链接也叫符号链接文件和硬链接文件软链接文件也就是前面给大家的 Linux 系统下的七种文件类型之一其作用类似于 Windows 下的快捷方式。 从使用角度来讲两者没有任何区别都与正常的文件访问方式一样支持读、写以及执行。 使用 ln 命令可以为一个文件创建软链接文件或硬链接文件用法如下 硬链接ln 源文件 链接文件 软链接ln -s 源文件 链接文件 从上图中可知使用 ln 命令创建的两个硬链接文件与源文件 test_file 都拥有相同的 inode 号既然inode 相同也就意味着它们指向了物理硬盘的同一个区块仅仅只是文件名字不同而已创建出来的硬链接文件与源文件对文件系统来说是完全平等的关系。每删除一个硬链接inode 节点上的链接数就会减一直到为 0inode 节点和对应的数据块才会被文件系统所回收也就意味着文件已经从文件系统中被删除了。 软链接文件与源文件有着不同的 inode 号如下图所示所以也就是意味着它们之间有着不同的数据块但是软链接文件的数据块中存储的是源文件的路径名链接文件可以通过这个路径找到被链接的源文件它们之间类似于一种“主从”关系当源文件被删除之后软链接文件依然存在但此时它指向的是一个无效的文件路径这种链接文件被称为悬空链接。 介绍完它们之间的区别之后大家可能觉得硬链接相对于软链接来说有较大的优势其实并不是这样对于硬链接来说存在一些限制情况如下 ⚫ 不能对目录创建硬链接超级用户可以创建但必须在底层文件系统支持的情况下。 ⚫ 硬链接通常要求链接文件和源文件位于同一文件系统中。 而软链接文件的使用并没有上述限制条件优点如下所示 ⚫ 可以对目录创建软链接 ⚫ 可以跨越不同文件系统 ⚫ 可以对不存在的文件创建软链接。 1、创建链接文件 创建硬链接 link() link()系统调用用于创建硬链接文件函数原型如下可通过man 2 link命令查看 #include unistd.h int link(const char *oldpath, const char *newpath);oldpath用于指定被链接的源文件路径应避免 oldpath 参数指定为软链接文件为软链接文件创建硬链接没有意义虽然并不会报错。 newpath用于指定硬链接文件路径如果 newpath 指定的文件路径已存在则会产生错误。返回值成功返回 0失败将返回-1并且会设置 errno。 link 函数测试 #include stdio.h #include stdlib.h #include unistd.h int main(void) {int ret;ret link(./test_file, ./hard);if (-1 ret) {perror(link error);exit(-1);}exit(0); }程序中通过 link 函数为当前目录下的 test_file 文件创建了一个硬链接 hard编译测试 创建软链接 symlink() #include unistd.h int symlink(const char *target, const char *linkpath);函数参数和返回值含义如下 target用于指定被链接的源文件路径target 参数指定的也可以是一个软链接文件。 linkpath用于指定硬链接文件路径如果 newpath 指定的文件路径已存在则会产生错误。 返回值成功返回 0失败将返回-1并会设置 errno。 创建软链接时并不要求 target 参数指定的文件路径已经存在如果文件不存在那么创建的软链接将成为“悬空链接”。 symlink 函数测试 #include stdio.h #include stdlib.h #include unistd.hint main(void) {int ret;ret symlink(./test_file, ./soft);if (-1 ret) {perror(symlink error);exit(-1);}exit(0); }2、读取软链接文件 #include unistd.h ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);函数参数和返回值含义如下 pathname需要读取的软链接文件路径。只能是软链接文件路径不能是其它类型文件否则调用函数将报错。 buf用于存放路径信息的缓冲区。 bufsiz读取大小一般读取的大小需要大于链接文件数据块中存储的文件路径信息字节大小。 返回值失败将返回-1并会设置 errno成功将返回读取到的字节数。 readlink 函数测试 #include stdio.h #include stdlib.h #include unistd.h #include string.h int main(void) {char buf[50];int ret;memset(buf, 0x0, sizeof(buf));ret readlink(./soft, buf, sizeof(buf));if (-1 ret) {perror(readlink error);exit(-1);}printf(%s\n, buf);exit(0); }使用 readlink 函数读取当前目录下的软链接文件 soft并将读取到的信息打印出来测试如下 七、目录 struct dirent {ino_t d_ino; /* inode 编号 */off_t d_off; /* not an offset; see NOTES */unsigned short d_reclen; /* length of this record */unsigned char d_type; /* type of file; not supported by all filesystem types */char d_name[256]; /* 文件名 */ };#include stdio.h #include stdlib.h #include dirent.h #include sys/types.h #include errno.h int main(void) {struct dirent *dir;DIR *dirp;int ret 0;/* 打开目录 */dirp opendir(./my_dir);if (NULL dirp) {perror(opendir error);exit(-1);}/* 循环读取目录流中的所有目录条目 */errno 0;while (NULL ! (dir readdir(dirp)))printf(%s %ld\n, dir-d_name, dir-d_ino);if (0 ! errno) {perror(readdir error);ret -1;goto err;} elseprintf(End of directory!\n);err:closedir(dirp);exit(ret); }1、进程的当前工作目录 Linux 下的每一个进程都有自己的当前工作目录current working directory当前工作目录是该进程解析、搜索相对路径名的起点不是以 / 斜杆开头的绝对路径。譬如代码中调用 open 函数打开文件时传入的文件路径使用相对路径方式进行表示那么该进程解析这个相对路径名时、会以进程的当前工作目录作为参考目录。 #include stdio.h #include stdlib.h #include unistd.h #include string.hint main(void) {char buf[100];char *ptr;memset(buf, 0x0, sizeof(buf));ptr getcwd(buf, sizeof(buf)); //获取进程工作目录if (NULL ptr) {perror(getcwd error);exit(-1);}printf(Current working directory: %s\n, buf);exit(0); }改变当前工作目录 #include stdio.h #include stdlib.h #include unistd.h #include string.hint main(void) {char buf[100];char *ptr;int ret;/* 获取更改前的工作目录 */memset(buf, 0x0, sizeof(buf));ptr getcwd(buf, sizeof(buf));if (NULL ptr) {perror(getcwd error);exit(-1);}printf(Before the change: %s\n, buf);/* 更改进程的当前工作目录 */ret chdir(./new_dir);if (-1 ret) {perror(chdir error);exit(-1);}/* 获取更改后的工作目录 */memset(buf, 0x0, sizeof(buf));ptr getcwd(buf, sizeof(buf));if (NULL ptr) {perror(getcwd error);exit(-1);}printf(After the change: %s\n, buf);exit(0); }2、删除文件 使用 unlink 函数删除文件 #include unistd.h int unlink(const char *pathname);函数参数和返回值含义如下 pathname需要删除的文件路径可使用相对路径、也可使用绝对路径如果 pathname 参数指定的文件不存在则调用 unlink()失败。 返回值成功返回 0失败将返回-1并设置 errno。 #include stdio.h #include stdlib.h #include unistd.h int main(void) {int ret;ret unlink(./test_file);if (-1 ret) {perror(unlink error);exit(-1);}exit(0); }使用 remove 函数删除文件 #include stdio.h int remove(const char *pathname);#include stdio.h #include stdlib.h int main(void) {int ret;ret remove(./test_file);if (-1 ret) {perror(remove error);exit(-1);}exit(0); }八、文件重命名 #include stdio.h int rename(const char *oldpath, const char *newpath);函数参数和返回值含义如下 oldpath原文件路径。 newpath新文件路径。 返回值成功返回 0失败将返回-1并设置 errno。 根据 oldpath、newpath 的不同有以下不同的情况需要进行说明 ⚫ 若 newpath 参数指定的文件或目录已经存在则将其覆盖 ⚫ 若 newpath 和 oldpath 指向同一个文件则不发生变化且调用成功。 ⚫ rename()系统调用对其两个参数中的软链接均不进行解引用。如果 oldpath 是一个软链接那么将重命名该软链接如果 newpath 是一个软链接则会将其移除、被覆盖。 ⚫ 如果 oldpath 指代文件而非目录那么就不能将 newpath 指定为一个目录的路径名。要想重命名一个文件到某一个目录下newpath 必须包含新的文件名。 ⚫ 如果 oldpath 指代为一个目录在这种情况下newpath 要么不存在要么必须指定为一个空目录。 ⚫ oldpath 和 newpath 所指代的文件必须位于同一文件系统。由前面的介绍可以得出此结论 ⚫ 不能对.当前目录和…上一级目录进行重命名。 #include stdio.h #include stdlib.h int main(void) {int ret;ret rename(./test_file, ./new_file);if (-1 ret) {perror(rename error);exit(-1);}exit(0); }九、总结 开头先给大家介绍 Linux 系统下的 7 种文件类型包括普通文件、目录、设备文件字符设备文件、块设备文件、符号链接文件软链接文件、管道文件以及套接字文件。 接着围绕 stat 系统调用详细给大家介绍了 struct stat 结构体中的每一个成员这使得我们对 Linux 下文件的各个属性都有所了解。接着分别给大家详细介绍了文件属主、文件访问权限、文件时间戳、软链接与硬链接以及目录等相关内容让大家知道在应用编程中如何去修改文件的这些属性以及它们所需要满足的条件。
http://www.tj-hxxt.cn/news/229156.html

相关文章:

  • 网站建设最关键的两个素材做php网站用什么软件开发
  • 做公司网站比较好的wordpress知更鸟打赏
  • 成都网站建设空间ui设计在哪个网站可以接做
  • 粤icp备网站建设 中企动力广州网站形式
  • app应用下载网站源码免备案网站主机
  • 房地产景区网站建设方案百度推广联系方式
  • 国外做网站wordpress搜索页制作
  • 营销网站建设哪里好薇wordpress分享qq
  • 长春高铁站数据分析网页
  • 解决wordpress更改新域名后网站不能访问的问题wordpress 调取页面缩略图
  • 南京网站制作网页河北省最新消息
  • 政务公开加强网站规范化建设python基础教程第4版pdf
  • 免费企业网站怎么做做壁画在哪个网站
  • 网站建设的可行性分析网站如何做mip
  • 网站建设礼品海阳网网站
  • 怎么做直播网站超管wordpress加一个字段
  • 深圳网站优化方案微信营销的模式有哪些
  • 简要说明网站建设的步骤塘下网站建设
  • 天津建设集团网站wordpress免费汉化企业主题
  • 那里有做像美团的网站的wordpress 制作网页
  • 兰州优化网站排名重庆网站建设冒号
  • 自己有了域名 怎么做网站搜多多搜索引擎入口
  • 室内设计网站平面案例太原百度快速优化排名
  • 做旅游网站的开题报告怎么做网页的搜索功能
  • 公司做个网站好还是做公众号好给教育类做网站
  • 网站开发维护公司经营范围seo技术优化服务
  • 手机做推广比较好的网站有哪些北京代理记账财务公司
  • 用jsp做电影网站的界面保定哪里有做网站的
  • 网站建设交流qq带会员中心WordPress免费主题
  • 哪有专业做网站在线logo设计免费生成器