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

润滑油东莞网站建设全屋设计培训哪里有?

润滑油东莞网站建设,全屋设计培训哪里有?,我国有哪些企业网站,网站建设详细报价文章目录并发与竞争的概念原子操作原子整形操作 API 函数原子位操作 API 函数自旋锁自旋锁简介自旋锁结构体自旋锁 API 函数自旋锁的注意事项读写自旋锁读写自旋锁的API顺序锁顺序锁的APIRCU(Read-Copy-Update)RCU的API信号量信号量API互斥体互斥体的API完成量(Completion)完成… 文章目录并发与竞争的概念原子操作原子整形操作 API 函数原子位操作 API 函数自旋锁自旋锁简介自旋锁结构体自旋锁 API 函数自旋锁的注意事项读写自旋锁读写自旋锁的API顺序锁顺序锁的APIRCU(Read-Copy-Update)RCU的API信号量信号量API互斥体互斥体的API完成量(Completion)完成量的API并发与竞争的概念 Linux 系统是个多任务操作系统会存在多个任务同时访问同一片内存区域这些任务可 能会相互覆盖这段内存中的数据造成内存数据混乱。 针对这个问题必须要做处理严重的话可能会导致系统崩溃。 linux存在以下并发访问: ①、多线程并发访问Linux 是多任务(线程)的系统所以多线程访问是最基本的原因。 ②、抢占式并发访问从 2.6 版本内核开始Linux 内核支持抢占也就是说调度程序可以 在任意时刻抢占正在运行的线程从而运行其他的线程。 ③、中断程序并发访问这个无需多说学过 STM32 应该知道硬件中断的权利可 是很大的。 ④、SMP(多核)核间并发访问现在 ARM 架构的多核 SOC 很常见多核 CPU 存在核间并 发访问。 原子操作 原子操作就是指不能再进一步分割的操作 Linux 内核提供了一些原子操作 API 函数来完成此功能 这些API分为对整型数据操作, 以及位运算操作 原子整形操作 API 函数 函数描述ATOMIC_INIT(int i)定义原子变量的时候对其初始化。int atomic_read(atomic_t *v)读取 v 的值并且返回。void atomic_set(atomic_t *v, int i)向 v 写入 i 值。void atomic_add(int i, atomic_t *v)给 v 加上 i 值。void atomic_sub(int i, atomic_t *v)从 v 减去 i 值。void atomic_inc(atomic_t *v)给 v 加 1也就是自增。void atomic_dec(atomic_t *v)从 v 减 1也就是自减int atomic_dec_return(atomic_t *v)从 v 减 1并且返回 v 的值。int atomic_inc_return(atomic_t *v)给 v 加 1并且返回 v 的值。int atomic_sub_and_test(int i, atomic_t *v)从 v 减 i如果结果为 0 就返回真否则返回假int atomic_dec_and_test(atomic_t *v)从 v 减 1如果结果为 0 就返回真否则返回假int atomic_inc_and_test(atomic_t *v)给 v 加 1如果结果为 0 就返回真否则返回假int atomic_add_negative(int i, atomic_t *v)给 v 加 i如果结果为负就返回真否则返回假 原子位操作 API 函数 函数描述void set_bit(int nr, void *p)将 p 地址的第 nr 位置 1。void clear_bit(int nr,void *p)将 p 地址的第 nr 位清零。void change_bit(int nr, void *p)将 p 地址的第 nr 位进行翻转。int test_bit(int nr, void *p)获取 p 地址的第 nr 位的值。int test_and_set_bit(int nr, void *p)将 p 地址的第 nr 位置 1并且返回 nr 位原来的值。int test_and_clear_bit(int nr, void *p)将 p 地址的第 nr 位清零并且返回 nr 位原来的值。int test_and_change_bit(int nr, void *p)将 p 地址的第 nr 位翻转并且返回 nr 位原来的值。 自旋锁 自旋锁简介 当一个线程要访问某个共享资源的时候首先要先获取相应的锁锁只能被一个线程持有 只要此线程不释放持有的锁那么其他的线程就不能获取此锁。对于自旋锁而言如果自旋锁 正在被线程 A 持有线程 B 想要获取自旋锁那么线程 B 就会处于忙循环-旋转-等待状态线 程 B 不会进入休眠状态或者说去做其他的处理而是会一直傻傻的在那里“转圈圈”的等待锁可用。 从这里我们可以看到自旋锁的一个缺点那就等待自旋锁的线程会一直处于自旋状态这样会浪 费处理器时间降低系统性能所以自旋锁的持有时间不能太长。所以自旋锁适用于短时期的轻 量级加锁如果遇到需要长时间持有锁的场景那就需要换其他的方法了 自旋锁结构体 typedef struct spinlock {union {struct raw_spinlock rlock;#ifdef CONFIG_DEBUG_LOCK_ALLOC# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))struct {u8 __padding[LOCK_PADSIZE];struct lockdep_map dep_map;};#endif};} spinlock_t;Linux 内核使用结构体 spinlock_t 表示自旋锁 自旋锁 API 函数 函数描述DEFINE_SPINLOCK(spinlock_t lock)定义并初始化一个自旋变量。int spin_lock_init(spinlock_t *lock)初始化自旋锁。void spin_lock(spinlock_t *lock)获取指定的自旋锁也叫做加锁。void spin_unlock(spinlock_t *lock)释放指定的自旋锁。int spin_trylock(spinlock_t *lock)尝试获取指定的自旋锁如果没有获取到就返回 0int spin_is_locked(spinlock_t *lock)检查指定的自旋锁是否被获取如果没有被获取就返回非 0否则返回 0。 自旋锁API函数适用于SMP或支持抢占的单CPU下线程之间的并发访问 中断里面可以使用自旋锁但是在中断里面使用自旋锁的时候在获取锁之前一定要先禁止本地中断(也就是本 CPU 中断对于多核 SOC来说会有多个 CPU 核)否则可能导致锁死现象的发生 SMP是指多个核心运行一个操作系统该操作系统同等的管理多个内核这种运行模式就是简单提高运行性能。目前支持该运行模式的操作系统有LinuxWindowsVxworks。 AMP的运行模式基本不会存在开销问题尤其是在运行裸机程序时甚至没有开销这种模式比较适合实时性高的应用。但是两个核心之间的通信与资源共享需要有一套优秀的处理机制。 BMP运行模式与 SMP类似同样也是一个OS管理所有的核心但开发者可以指定将某个任务仅在某个指定内核上执行 。 函数描述void spin_lock_irq(spinlock_t *lock)禁止本地中断并获取自旋锁。void spin_unlock_irq(spinlock_t *lock)激活本地中断并释放自旋锁。void spin_lock_irqsave(spinlock_t *lock, unsigned long flags)保存中断状态禁止本地中断并获取自旋锁。void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)将中断状态恢复到以前的状态并且激活本地中断释放自旋锁。 自旋锁的注意事项 ①、因为在等待自旋锁的时候处于“自旋”状态因此锁的持有时间不能太长一定要 短否则的话会降低系统性能。如果临界区比较大运行时间比较长的话要选择其他的并发处 理方式比如稍后要讲的信号量和互斥体。 ②、自旋锁保护的临界区内不能调用任何可能引起进程调度 API函数否则的话可能 导致死锁。 如调用copy_from_user(), copy_to_user(), kmalloc(), msleep()等函数, 有可能导致内核崩溃 ③、不能递归申请自旋锁因为一旦通过递归的方式申请一个你正在持有的锁那么你就 必须“自旋”等待锁被释放然而你正处于“自旋”状态根本没法释放锁。结果就是自己 把自己锁死了 ④、在编写驱动程序的时候我们必须考虑到驱动的可移植性因此不管你用的是单核的还 是多核的 SOC都将其当做多核 SOC来编写驱动程序。 在单核的情况下, 若中断和进程可能访问同一临界 区, 进程里调用spin_lock_irqsave()是安全的, 在中断里其实不调用spin_lock()也没问题, 因为spin_ lock_irqsave()可以保证这个cpu的中断服务不被执行. 但是, 如果cpu变成多核, spin_lock_irqsave()不能屏蔽 另一个cpu的中断, 所以另一个核就可能造成并发问题, 因此无论如何, 我们在中断服务程序里也应该调用spin_lock(). 读写自旋锁 自旋锁不关心锁定的临界区究竟在进行什么操作, 不管是读还是写 实际上, 对共享资源并发访问, 多个执行单元同时读取是不会有问题的, 自旋锁衍生的读写自旋锁(rwlock)可允许读 的操作并发. 读写自旋锁的API 读写锁操作 API函数分为两部分一个是给读使用的一个是给写使用的 函数描述DEFINE_RWLOCK(rwlock_t lock)定义并初始化读写锁void rwlock_init(rwlock_t *lock)初始化读写锁。 读锁 函数描述void read_lock(rwlock_t *lock)获取读锁。void read_unlock(rwlock_t *lock)释放读锁。void read_lock_irq(rwlock_t *lock)禁止本地中断并且获取读锁。void read_unlock_irq(rwlock_t *lock)打开本地中断并且释放读锁。void read_lock_irqsave(rwlock_t *lock, unsigned long flags)保存中断状态禁止本地中断并获取读锁。void read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)将中断状态恢复到以前的状态并且激活本地中断释放读锁。void read_lock_bh(rwlock_t *lock)关闭下半部并获取读锁。void read_unlock_bh(rwlock_t *lock)打开下半部并释放读锁。 写锁 函数描述void write_lock(rwlock_t *lock)获取写锁。void write_unlock(rwlock_t *lock)释放写锁。void write_lock_irq(rwlock_t *lock)禁止本地中断并且获取写锁。void write_unlock_irq(rwlock_t *lock)打开本地中断并且释放写锁。void write_lock_irqsave(rwlock_t *lock, unsigned long flags)保存中断状态禁止本地中断并获取写锁。void write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)将中断状态恢复到以前的状态并且激活本地中断释放读锁。void write_lock_bh(rwlock_t *lock)关闭下半部并获取读锁。void write_unlock_bh(rwlock_t *lock)打开下半部并释放读锁。 顺序锁 顺序锁是对读写锁的一种优化, 若使用顺序锁, 读执行单元不会被写执行单元阻塞, 也就是说, 读执行单元在写执行单元对被顺序锁保护的共享资源进行写操作时仍然可以继续读, 而不必等待写执行单元完成写操作, 写执行单元也不需要等待读执行单元完成读操作再进行写操作. 但是写执行单元与写执行单元之间仍然互斥. 尽管读写之间不互斥, 但是如果读执行单元操作期间, 写执行单元已经发生了写操作, 那么, 读执行单元必需重新读取数据. 以便确保数据时完整的. 所以, 这种情况下, 读端可能反复读多次同样的区域才能得到有效的数据. 顺序锁的API 获取顺序锁 函数描述void write_seqlock(seqlock_t *sl)获取顺序锁void write_seqlock_irqsave(seqlock_t *lock, unsigned long flags)保存中断状态禁止本地中断并获取顺序锁。void write_seqlock_irq(seqlock_t *lock)禁止本地中断并且获取顺序锁void write_seqlock_bh(seqlock_t *lock)关闭下半部并获取顺序锁 释放顺序锁 函数描述void write_sequnlock(seqlock_t *sl)释放顺序锁void wirte_sequnlock_irqrestore(seqlock *sl, unsigned long flags)将中断状态恢复到以前的状态并且激活本地中断,释放顺序锁void write_sequnlock_irq(seqlock *sl)打开本地中断并且释放顺序锁。void write_sequnlock_bh(seqlock *sl)打开下半部并释放顺序锁。 读开始 函数unsigned read_seqbegin(const seqlock_t *sl)unsigned read_seqbegin_irqsave(const seqlock_t *sl, flags) 读执行单在对被顺序锁sl保护的共享资源进行访问前需要调用该函数, 该函数返回顺序锁sl的当前顺序号. 重读 函数int read_seqretry(const seqlock_t *sl, unsigned iv)int read_seqretry_irqrestore(const seqlock_t *sl, flags) 读执行单元在访问完被顺序锁sl保护的共享资源后需要调用该函数来检查, 在读访问期间是否有写操作, 如果有写操作, 读执行单元就需要重新进行读操作 顺序锁的使用模式如下: do{seqnum read_seqbegin(seqlock_a);读操作代码 }while(read_seqretry(seqlock_a, seqnum));RCU(Read-Copy-Update) RCU工作原理: 不同于自旋锁, 使用RCU的读端没有锁, 内存屏障, 原子指令类的开销, 几乎可以认为是直接读(知识简单的标明开始和结束), 而RCU的写执行单元在访问它的共享资源前复制一个副本, 然后对副本进行修改, 最后使用一个回调机制在适当的时机把指向原来数据的指针重新指向新的被修改的数据, 这个时机就是所有引用该数据的CPU都退出对共享数据读操作的时候, 等待适当的时机这一时期称为宽限期. 例子: 进程A通过RCU修改某链表的N节点内容, RCU通过构造一个新的M节点, 在M节点中修改内容, 并用M节点代替N节点, 之后进程A等待在链表前期已经存在的所有读端结束后(即宽限期, 通过synchronize_rcu()API完成), 再释放原来的N节点. 假设存在一个链表: struct foo{struct list_head list;int a;int b;int c; }; LIST_HEAD(head) ... p search(head, key); if(p NULL){//... } q kmalloc(sizeof(*p), GFP_KERNEL); *q *p; q-b 2; q-c 3; list_replace_rcu(p-list, q-list); synchronize_rcu(); kfree(p);RCU的API 读锁定 rcu_read_lock() rcu_read_lock_bh() 读解锁 rcu_read_unlock() rc_read_unlock_bh() 同步RCU synchronize_rcu() 该函数由RCU写执行单元调用, 它将阻塞写执行单元, 直到当前CPU上所有的已经存在的读执行单元完成读临界区, 写执行单元才可以继续下一步操作.synchronize_rcu()并不需要等待后续读临界区的完成. 挂接回调 void call_rcu(struct rcu_head* head, void (*func)(struct rcu_head *rcu)); call_rcu()由RCU写执行单元调用, 与synchronize_rcu()不同的是, 它不会使写执行单元阻塞, 因而可以再中断上下文或软中断中使用. 该函数把函数func挂接到rcu回调函数链上, 然后立即返回, 挂接的回调函数会在一个宽限期结束后被执行. rcu_assign_pointer(p, v) 给RCU保护的指针赋一个新的值 rcu_dereference(p) 读端使用rcu_dereference()获取一个RCU保护的指针, 之后既可以安全的引用它, 一般需要在rcu_read_lock()/rcu_read_unlock()保护的区间引用这个指针 rcu_access_pointer(p) 读端使用rcu_access_pointer()获取一个RCU保护的指针, 之后并不引用它, 这种情况下, 我们只关心指针本身的值, 比如可以使用该函数判断指针是否为NULL ex: 把rcu_assign_pointer() rcu_dereference()结合, 写端分配一个新的 struct foo内存, 初始化其中的成员, 之后把该结构体的地址赋值给全局的gp指针: struct foo{int a;int b;int c; }; struct foo *gp NULL;p kmalloc(sizeof(*p), GFP_KERNEL); p-a 1; p-b 2; p-c 3; rcu_assign_pointer(gp, p);读端访问该片区: rcu_read_lock(); p rcu_dereference(gp); if(p ! NULL){do_something_with(p-a, p-b, p-c); } rcu_read_unlock();对于链表数据结构而言, Linux内核增加了专门给RCU保护的链表操作API static inline void list_add_rcu(struct list_head *new, struct list_head *head); 该函数把链表元素new插入RCU保护的链表head的开头 static inline void list_add_tail_rcu(struct list_head *new, struct list_head *head); 该函数将元素new添加到被RCU保护的链表的尾部 static inline void list_del_rcu(struct list_head *entry); 该函数从RCU保护的链表中删除指定的元素entry. static inline void list_replace_rcu(struct list_head *old, struct list_head *new); 它使用新的链表元素new取代旧的链表元素old list_for_each_entry_rcu(pos, head) 该宏用于遍历由RCU保护的链表head, 只要在读执行单元临界区使用该函数, 它就可以安全的和其他RCU保护的链表操作函数(如list_add_rcu())并发运行. ex: 链表写端代码 struct foo{struct list_head list;int a;int b;int c; }; LIST_HEAD(head);p kmalloc(sizeof(*p), GFP_KERNEL); p-a 1; p-b 2; p-c 3; list_add(p-list, head);链表读端代码 rcu_read_lock(); list_for_each_entry_rcu(p, head, list) if(p ! NULL){do_something_with(p-a, p-b, p-c); } rcu_read_unlock(); 信号量 相比于自旋锁信号量可以使线程进入休眠状态,信号量的开销要比自旋锁大因为信号量使 线程进入休眠状态以后会切换线程切换线程就会有开销。 ①、因为信号量可以使等待资源线程进入休眠状态因此适用于那些占用资源比较久的场 合。 ②、因此信号量不能用于中断中因为信号量会引起休眠中断不能休眠。 (也有不休眠的信号量API) ③、如果共享资源的持有时间比较短那就不适合使用信号量了因为频繁的休眠、切换 线程引起的开销要远大于信号量带来的那点优势。 信号量结构体: struct semaphore { raw_spinlock_t lock; unsigned int count; struct list_head wait_list; };信号量API 函数描述DEFINE_SEAMPHORE(name)定义一个信号量并且设置信号量的值为 1。void sema_init(struct semaphore *sem, int val)初始化信号量 sem设置信号量值为 val。void down(struct semaphore *sem)获取信号量因为会导致休眠因此不能在中断中使用。int down_trylock(struct semaphore *sem);尝试获取信号量如果能获取到信号量就获取并且返回 0。如果不能就返回非 0并且不会进入休眠。int down_interruptible(struct semaphore *sem)获取信号量和 down类似只是使用 down进入休眠状态的线程不能被信号打断。而使用此函数进入休眠以后是可以被信号打断的。void up(struct semaphore *sem)释放信号量 互斥体 将信号量的值设置为 1就可以使用信号量进行互斥访问了虽然可以通过信号量实现互斥但是 Linux提供了一个比信号量更专业的机制来进行互斥它就是互斥体—mutex。互斥访问表示一次只有一个线程可以访问共享资源不能递归申请互斥体。在我们编写 Linux驱动的时候遇到需要互斥访问的地方建议使用 mutex。Linux内核使用 mutex结构体表示互斥体定义如下: struct mutex { /* 1: unlocked, 0: locked, negative: locked, possible waiters */ atomic_t count; spinlock_t wait_lock; };在使用 mutex之前要先定义一个 mutex变量。在使用 mutex的时候要注意如下几点 ①、mutex可以导致休眠因此不能在中断中使用 mutex中断中只能使用自旋锁。 ②、和信号量一样mutex保护的临界区可以调用引起阻塞的 API函数。 ③、因为一次只有一个线程可以持有 mutex因此必须由 mutex的持有者释放 mutex。并且 mutex不能递归上锁和解锁。 互斥体的API 函数描述DEFINE_MUTEX(name)定义并初始化一个 mutex变量。void mutex_init(mutex *lock)初始化 mutex。void mutex_lock(struct mutex *lock)获取 mutex也就是给 mutex上锁。如果获取不到就进休眠。void mutex_unlock(struct mutex *lock)释放 mutex也就给 mutex解锁。int mutex_trylock(struct mutex *lock)尝试获取 mutex如果成功就返回 1如果失败就返回 0。int mutex_is_locked(struct mutex *lock)判断 mutex是否被获取如果是的话就返回1否则返回 0。int mutex_lock_interruptible(struct mutex *lock)使用此函数获取信号量失败进入休眠以后可以被信号打断。 完成量(Completion) 用于一个执行单元等待另一个执行单元执行完某事 完成量的API 定义完成量 struct completion my_completion; 初始化完成量 初始化或者重新初始化my_completion这个完成量的值为0(即没有完成的状态) init_completion(my_completion); reinit_completion(my_completion) 等待完成量 等待一个完成量被唤醒: void wait_for_completion(struct completion *c); 唤醒完成量 void complete(struct completion *c); 只唤醒一个等待的执行单元 void complete_all(struct completion *c); 释放所有等待同一完成量的执行单元
文章转载自:
http://www.morning.nhlnh.cn.gov.cn.nhlnh.cn
http://www.morning.pqkgb.cn.gov.cn.pqkgb.cn
http://www.morning.bpmdz.cn.gov.cn.bpmdz.cn
http://www.morning.rcdmp.cn.gov.cn.rcdmp.cn
http://www.morning.rxnl.cn.gov.cn.rxnl.cn
http://www.morning.stsnf.cn.gov.cn.stsnf.cn
http://www.morning.lnfkd.cn.gov.cn.lnfkd.cn
http://www.morning.twpq.cn.gov.cn.twpq.cn
http://www.morning.diuchai.com.gov.cn.diuchai.com
http://www.morning.npxcc.cn.gov.cn.npxcc.cn
http://www.morning.xqxlb.cn.gov.cn.xqxlb.cn
http://www.morning.tqrbl.cn.gov.cn.tqrbl.cn
http://www.morning.qczjc.cn.gov.cn.qczjc.cn
http://www.morning.hxxwq.cn.gov.cn.hxxwq.cn
http://www.morning.snxbf.cn.gov.cn.snxbf.cn
http://www.morning.rdfq.cn.gov.cn.rdfq.cn
http://www.morning.trsmb.cn.gov.cn.trsmb.cn
http://www.morning.qpnmd.cn.gov.cn.qpnmd.cn
http://www.morning.cyysq.cn.gov.cn.cyysq.cn
http://www.morning.kmbgl.cn.gov.cn.kmbgl.cn
http://www.morning.nrfrd.cn.gov.cn.nrfrd.cn
http://www.morning.cfqyx.cn.gov.cn.cfqyx.cn
http://www.morning.mnqz.cn.gov.cn.mnqz.cn
http://www.morning.qnbsx.cn.gov.cn.qnbsx.cn
http://www.morning.qhtlq.cn.gov.cn.qhtlq.cn
http://www.morning.pmdlk.cn.gov.cn.pmdlk.cn
http://www.morning.qkqhr.cn.gov.cn.qkqhr.cn
http://www.morning.clzly.cn.gov.cn.clzly.cn
http://www.morning.xylxm.cn.gov.cn.xylxm.cn
http://www.morning.jrwbl.cn.gov.cn.jrwbl.cn
http://www.morning.lwbhw.cn.gov.cn.lwbhw.cn
http://www.morning.ymwnc.cn.gov.cn.ymwnc.cn
http://www.morning.nrydm.cn.gov.cn.nrydm.cn
http://www.morning.thbqp.cn.gov.cn.thbqp.cn
http://www.morning.ydnxm.cn.gov.cn.ydnxm.cn
http://www.morning.brtxg.cn.gov.cn.brtxg.cn
http://www.morning.hbhnh.cn.gov.cn.hbhnh.cn
http://www.morning.mgbsp.cn.gov.cn.mgbsp.cn
http://www.morning.rzbgn.cn.gov.cn.rzbgn.cn
http://www.morning.skbbt.cn.gov.cn.skbbt.cn
http://www.morning.jcyrs.cn.gov.cn.jcyrs.cn
http://www.morning.wjlnz.cn.gov.cn.wjlnz.cn
http://www.morning.ljmbd.cn.gov.cn.ljmbd.cn
http://www.morning.tsqrc.cn.gov.cn.tsqrc.cn
http://www.morning.mqbzk.cn.gov.cn.mqbzk.cn
http://www.morning.ytnn.cn.gov.cn.ytnn.cn
http://www.morning.qnzld.cn.gov.cn.qnzld.cn
http://www.morning.nlkhr.cn.gov.cn.nlkhr.cn
http://www.morning.yzxhk.cn.gov.cn.yzxhk.cn
http://www.morning.mmhyx.cn.gov.cn.mmhyx.cn
http://www.morning.ktblf.cn.gov.cn.ktblf.cn
http://www.morning.bbtn.cn.gov.cn.bbtn.cn
http://www.morning.wdqhg.cn.gov.cn.wdqhg.cn
http://www.morning.bbtn.cn.gov.cn.bbtn.cn
http://www.morning.khclr.cn.gov.cn.khclr.cn
http://www.morning.hxxwq.cn.gov.cn.hxxwq.cn
http://www.morning.nbfkk.cn.gov.cn.nbfkk.cn
http://www.morning.phlwj.cn.gov.cn.phlwj.cn
http://www.morning.wjjxr.cn.gov.cn.wjjxr.cn
http://www.morning.sgwr.cn.gov.cn.sgwr.cn
http://www.morning.qkskm.cn.gov.cn.qkskm.cn
http://www.morning.rpfpx.cn.gov.cn.rpfpx.cn
http://www.morning.pmftz.cn.gov.cn.pmftz.cn
http://www.morning.srbl.cn.gov.cn.srbl.cn
http://www.morning.nwczt.cn.gov.cn.nwczt.cn
http://www.morning.jbshh.cn.gov.cn.jbshh.cn
http://www.morning.dwkfx.cn.gov.cn.dwkfx.cn
http://www.morning.ljglc.cn.gov.cn.ljglc.cn
http://www.morning.ldmtq.cn.gov.cn.ldmtq.cn
http://www.morning.rhkgz.cn.gov.cn.rhkgz.cn
http://www.morning.gtkyr.cn.gov.cn.gtkyr.cn
http://www.morning.lszjq.cn.gov.cn.lszjq.cn
http://www.morning.c7624.cn.gov.cn.c7624.cn
http://www.morning.mdfxn.cn.gov.cn.mdfxn.cn
http://www.morning.jybj.cn.gov.cn.jybj.cn
http://www.morning.rtbhz.cn.gov.cn.rtbhz.cn
http://www.morning.rgpsq.cn.gov.cn.rgpsq.cn
http://www.morning.bkylg.cn.gov.cn.bkylg.cn
http://www.morning.qsmdd.cn.gov.cn.qsmdd.cn
http://www.morning.cokcb.cn.gov.cn.cokcb.cn
http://www.tj-hxxt.cn/news/271896.html

相关文章:

  • 湖北网站设计网站更改指定字段
  • 雄安做网站价格wordpress 一直跳转到老域名
  • 公司内部 网站开发中企动力的网站如何
  • 鸿邑网站建设查询注册过的网站
  • 网站源码提取天津百度首页优化排名
  • app 网站平台建设实施方案想做一个能上传视频的网站怎么做
  • html5手机网站下载驻马店建设网站
  • 个人网站制作的主要内容河南中建卓越建设管理有限公司网站
  • 怎么做二手房网站清溪网站建设公司
  • h5网站案例my网站域名
  • 苏州制作企业网站的网站搭建就来徐州百度网络非常好
  • 教研组网站的建设wordpress如何创建分类
  • 网站制作学什么软件有哪些微信公众号被收费299
  • 网站建设需要多少内存施工单位招聘信息
  • 网站开发流程的8个步骤wordpress商业模板个人
  • 整人网站建设有什么平台可以免费发布推广信息
  • 网站上怎么做图片变换动图做商城网站简单吗
  • 什么叫域名访问网站软件技术有学做网站吗
  • ppt图标网站链接怎么做虚拟主机做多个网站
  • 东莞网站制作企业网站陕西大型网站建设
  • 大连网站怎么云搜索app
  • 开网站需要多少钱上海模板开发建站
  • 做博客网站怎么赚钱吗江宁外贸网站建设
  • 天河建设网站多少钱建站哪家好就要用兴田德润
  • 10.制作一个网站一般先要明确( )网站开发asp 视频教程
  • 做网站大概要多阳泉网站建设网站
  • 同城配送网站建设一般做网站用什么软件
  • 北京好的建站团队软件技术专业简介
  • 郑州建设局官方网站一级a做爰全过程网站
  • 广告型网站云匠网官网