设置->用户->导入书签和设置
最近,很多读者朋友都在反映IT工作的执行难度正变得越来越低。也许与十年前比起来,如今的IT部门确实拥有更加庞大的辅助工具阵营与技术支持,但情况是否真的与大家的感受相同呢?今天我们就来聊聊这个话题。
目前,我们已经完全能够以自动化方式进行服务器实例的创建与管理、部署复杂应用程序框架等工作。坐在自己的台式机面前、鼠标点击几下,服务器故障排查就此顺利实现。就在不久之前,这类维护工作还普遍需要我们搬动服务器机架、手动安装操作系统、亲自跑到数据中心、完成复杂的布线及网络配置等等。从这个角度来看,IT工作已经变得更清闲、更安逸。
然而随着时间的推移,我们发现只有不断对方案进行调整或改进,才能真正做到对管理流程、常见任务及工作负载的简化。要知道,技术事务的复杂性并没有降低——事实上当下的IT系统比以往任何时候都更复杂——我们只能说现在的技术人员从体力劳动中解脱了出来、也不必应付太多简单重复的枯燥任务。我们一直在将IT基本原理向抽象层面推进,努力把每项工作都变成日常管理链中的一环。这就要求从业人员在规划方面做出更多尝试,而初期投入的一切精力也确实很快带来效率及成本方面的显著回报。
虚拟化技术自然是实现这种进步的深层驱动力,如今不仅服务器引入了虚拟化,就连存储系统、应用程序也与虚拟化挂上了钩——甚至网络也在VMware的VXLAN等产品的帮助下正式迈向虚拟化时代。总体来说,这些组件的创建及部署工作对技术人员的业务水平提出了更高要求,同时也给日常管理与维护工作带来了极大便利。我们不必再为IT基础设施的规划与重建工作费心劳力,但项目初期的建设难度与投资金额相比过去则有了大幅度提高。
不过毫无疑问,IT工作并没有变得更“简单”。
日常操作的难度显著降低,许多问题甚至可以由普通员工“自助”解决,然而我们仍然被牢牢束缚在技术领域的各种疑难杂症及意外状况之上。一方面,我们很可能遇上一周前发生的AWS宕机等突发问题。这是一种负面影响很难快速清除的破坏性事态,感知度非常高(尤其是非IT人员),而且显然是由人为失误及规划缺失所造成。世界范围内的一切自动化体系都无法有效解决这类故障,相反自动化程度越高、对于源头设施的依赖性也越强,这进一步导致了后果的严重性。相信Amazon会在很长一段时间内笼罩在这次事故的阴影当中。
接下来,我们再看看像Mina Naguib最近所遭遇的特殊问题。我上周专门为此撰写了评述文章,因为这应该被当作一个典型范例,指导经验丰富、技能娴熟的管理员们如何准确发现并纠正在合理状况下本不应该出现的状况。无论是否符合逻辑,大家都应该抱着最坏的预期对基础设施中的所有层面进行故障排查。
1. 拒绝。这是一种偶然性很强的问题,故障几乎不可能重现,它涉及互联网中最稳定也最可靠的协议之一。理论上讲这类问题根本不应该发生。
2. 愤怒。 在利用一切合理思路进行故障分析及排除之后,问题仍然存在。这时挫败感恐怕已经不足以形容管理者的心情了。
3. 交涉。即使是最有经验的IT大师,偶尔也会希望能以一部分牺牲换来故障的快速解决。如果问题凭空出现、暂时无法做出理性解析,大多数技术人员往往需要为自己争取更多处理时间,借以完成监控及一致性检测。
4. 悲观。 这种情绪不一定会给技术人员本身带来影响,但在我亲身经历的许多实例中,负面反应往往会立刻感染管理层及其它一些与IT并不沾边的同事。他们开始放弃帮助管理员解决问题的努力,反而持观望态度或者粗暴地认为事情已无法挽回——一旦这种情绪占了上风,问题很可能永远得不到根本解决,甚至严重打击企业员工的士气。
5. 接受。这种态度可以被视为IT问题解决或者陷入悲观的分水岭。事实上IT部门在面对问题时根本就不应该涉及接受或者不接受,这是我们的工作,无论如何都必须成功修复。即使修复工作的效果在质量和可靠性方面还有待商榷,但面对问题选择放弃抵抗的家伙只能说根本不具备基本的职业操守。这不是什么选择题,我们必须搞定、工作必须继续。
Mina就遇上了非常少见的TCP失效故障,该问题是由网络服务供应商造成的,可以说与受影响的用户并无直接关系。某台路由器中的固件代码有bug、或者某个接口损坏最终导致了悲剧的发生,只有通过坚持不懈的关注、努力与精心调试,才能将这类罕见问题扼杀在萌芽状态。
这种故障就绝不是技术人员能简单通过点击鼠标或浏览社区就能解决的,绝大多数新手管理员甚至根本无法发现或者做出回应。总之,IT工作绝不简单,而这样的挑战就是难题的集中体现。
在公众的印象中,IT工作似乎变得更容易、更顺畅、更快速甚至更具时尚感,但实际上每一位技术工作者仍然需要拿出十几年甚至几十年磨练技能、积累经验、努力工作。业务所带来的压力已经从过去的物理层面转变成现在的逻辑层面,但身为IT人士,我们自己清楚这份责任比以往任何时候都更重大、更关键。
这两天在调一款触摸屏的驱动,在调试过程中发现,在休眠的时候,所用到的几个GPIO引脚的状态会自动变为低电平,在唤醒后又会回到高电平。但是在代码里并没有显式地去拉低/拉高。很明显这不是我们想要的,如果这样的话,GPIO的状态都无法自己控制,还怎么调呢?
问了下板子的FAE,GPIO的状态在休眠时,是预定义的。代码在
arch/mips/jz4770/boards/gps1/gps1-pm.c
其中gps1是板子类型
29 int gpio_sleep_state_table[][2] = { 30 /* GPIO Group - A */ 31 {32 * 0 + 0, GSS_INPUT_NOPULL}, /* NC */ 32 {32 * 0 + 1, GSS_INPUT_PULL }, /* ACC_INT2 input pull*/ 33 {32 * 0 + 2, GSS_IGNORE }, /* FVDD_EN */ 34 {32 * 0 + 3, GSS_INPUT_NOPULL}, /* SCLK */ 35 {32 * 0 + 4, GSS_INPUT_NOPULL}, /* NC */ 36 {32 * 0 + 5, GSS_INPUT_NOPULL}, /* NC */ 37 {32 * 0 + 6, GSS_INPUT_NOPULL}, /* PA6/SDATA */ 38 {32 * 0 + 7, GSS_INPUT_NOPULL}, /* NC */ 39 {32 * 0 + 8, GSS_INPUT_NOPULL}, /* NC */ 40 {32 * 0 + 9, GSS_INPUT_PULL }, /* ACC_INT1 input pull*/ 41 {32 * 0 + 10, GSS_INPUT_NOPULL}, /* NC */ 42 {32 * 0 + 11, GSS_INPUT_NOPULL}, /* NC */ 43 {32 * 0 + 12, GSS_INPUT_NOPULL}, /* NC */ 44 {32 * 0 + 13, GSS_INPUT_NOPULL}, /* NC */ 45 {32 * 0 + 14, GSS_INPUT_NOPULL}, /* NC */ 46 {32 * 0 + 15, GSS_INPUT_NOPULL}, /* NC */ 47 {32 * 0 + 16, GSS_INPUT_NOPULL}, /* NC */
....
这里进行了所有GPIO在休眠时的状态的预定义。
在arch/mips/jz4770/common/pm.c中
509 int __init gpio_sleep_state_check(void) 510 { 511 unsigned int i,state,group,index; 512 unsigned int panic_flags[6] = {0,}; 513 514 for(i = 0; i < GPIO_PORT_NUM; i++) 515 gpio_intput_pull[i] = 0xffffffff; 516 517 for(i = 0; gpio_sleep_state_table[i][1] != GSS_TABLET_END;i++) { 518 group = gpio_sleep_state_table[i][0] / 32; 519 index = gpio_sleep_state_table[i][0] % 32; 520 state = gpio_sleep_state_table[i][1]; 521 522 gpio_intput_pull[group] = gpio_intput_pull[group] & ~(1 << index); 523 if(panic_flags[group] & (1 << index)) { 524 printk("\nwarning : (%d line) same gpio already set before this line!\n",i); 525 printk("\nwarning : (%d line) same gpio already set before this line!\n",i); 526 printk("\nwarning : (%d line) same gpio already set before this line!\n",i); 527 printk("\nwarning : (%d line) same gpio already set before this line!\n",i); 528 printk("\nwarning : (%d line) same gpio already set before this line!\n",i); 529 printk("\nwarning : (%d line) same gpio already set before this line!\n",i); 530 printk("\nwarning : (%d line) same gpio already set before this line!\n",i); 531 panic("gpio_sleep_state_table has iterant gpio set , system halt\n"); 532 while(1); 533 } else { 534 panic_flags[group] |= 1 << index; 535 } 536
//这里对预设的各种状态进行处理 537 switch(state) { 538 case GSS_OUTPUT_HIGH:gpio_output_high[group] |= 1 << index;break; 539 case GSS_OUTPUT_LOW:gpio_output_low[group] |= 1 << index;break; 540 case GSS_INPUT_PULL:gpio_intput_pull[group] |= 1 << index;break; 541 case GSS_INPUT_NOPULL:gpio_intput_nopull[group] |= 1 << index;break; 542 } 543 } 544 545 for(i = 0; i < GPIO_PORT_NUM; i++) { 546 printk("%8x\t\t", gpio_output_low[i]); 547 printk("%8x\t\t", gpio_output_high[i]); 548 printk("%8x\t\t", gpio_intput_pull[i]); 549 printk("%8x\n", gpio_intput_nopull[i]); 550 } 551 552 return 0; 553 }
98 void jzsoc_do_sleep(unsigned long *ptr) 99 { 100 unsigned char i; 101 102 /* Print messages of GPIO registers for debug */ 103 print_gpio(); 104 /* Save GPIO registers */ 105 106 for(i = 0; i < GPIO_PORT_NUM; i++) { 107 *ptr++ = REG_GPIO_PXINT(i); 108 *ptr++ = REG_GPIO_PXMSK(i); 109 *ptr++ = REG_GPIO_PXPAT1(i); 110 *ptr++ = REG_GPIO_PXPAT0(i); 111 *ptr++ = REG_GPIO_PXPEN(i); 112 } 113 114 for(i = 0; i < GPIO_PORT_NUM; i++) { 115 __gpio_group_as_output_low(i, gpio_output_low[i]); 116 __gpio_group_as_output_high(i, gpio_output_high[i]); 117 __gpio_group_as_input_pull(i, gpio_intput_pull[i]); 118 __gpio_group_as_input_nopull(i, gpio_intput_nopull[i]); 119 }
如果我们想需要手动进行管理需要的GPIO口,只需要将预设的状态改为GSS_IGNORE即可。