Joyber 发布的文章

英文原文:https://osxlatitude.com/forums/topic/10267-understanding-and-patching-framebuffer-haswell/

首先以我最喜欢的Haswell为例。我使用的是移动平台ID 0x0a260006。

Haswell帧缓冲(AppleIntelFramebufferAzul):

如果您在十六进制编辑器中打开位于AppleIntelFramebufferAzul.kext的Contents / MacOS中的二进制文件,然后搜索“ 0600260A 01030303”

您将得到如下结果:

0600260A 01030303 00000002 00003001 00006000 其中值是:

0600260A->帧缓冲区/布局ID(0x0a260006)
01030303->管道和端口数(最后4个字节,不知道为什么会重复)
00000002-> DvMT内存(32MB,十进制1024 1024 32)
00003001->帧缓冲内存(十进制19MB 1024 1024 19)
00006000->光标内存(十进制为6MB 1024 1024 6)
注意: 帧缓冲内存+游标内存必须小于DvMT值,否则会出现内核崩溃(19 + 6 = 25,小于32MB)

现在我们知道了这些值所对应的内容,我们还知道我们的平台ID中包含3个端口,即0x03 = 3(十进制)。现在,如果您在十六进制编辑器中查找仅几个字节,您将获得帧缓冲区的端口。

AppleIntelFramebufferAzul在0600260A的端口:

00000800 02000000 30000000->端口0000属性(LVDS)
01050900 00040000 87000000->端口0105属性(DP)
02040900 00040000 87000000->端口0204属性(DP)
FF000000 01000000 40000000->茶几
注意: 第一组的前4个字节显示端口号。第二部分涉及连接器类型。现在让我们看一下常见的连接器类型。

连接器类型:

LVDS 0200
用于DP的0004
用于HDMI的0008
尽管在HD4400上可以使用OOB,但在真正的Mac上却找不到VGA。
修补帧缓冲区:

我们将介绍端口计数,HDMI,DvMT,Cursor mem,Framebuffer mem和删除端口的修补程序。

修补PortCount:

众所周知,我们的平台ID中有3个端口,用01030303表示, 现在假设我们要将端口数更改为2(用于从帧缓冲区中删除不需要的端口,从而解决了某些Haswell / Broadwell机器上的延迟)

因此,我们必须将03更改为02(因为重复了两次,所以我们必须更改该数据的最后4个字节)。将计数从3更改为2的端口计数更改端口为:

名称:AppleIntelFramebufferAzul

找到:0600260A 0103 0303 00000002

代表:0600260A 0103 0202 00000002

现在,当我们将端口数减少到2时,我们需要删除未使用的端口。使用一些常识,您可以知道我们无法删除LVDS端口,否则我们的笔记本电脑将无法显示任何内容。现在我们剩下2个备用端口了。其中之一将用于HDMI。就我而言,端口0204用于HDMI。

请注意,端口号很容易识别,因为它们在FrameBufferConnector的位置。就像,如果您运行:

nick @ Nicks - MacBook - Air :〜$ ioreg - l | grep “ AppleIntelFramebuffer类”

| | | + -o AppleIntelFramebuffer @ 0 <类AppleIntelFramebuffer ,ID 0x100000354 ,已注册,已匹配,活动,忙碌0 (41毫秒),保留20 > //端口1 | | | + -o AppleIntelFramebuffer @ 1 <类AppleIntelFramebuffer ,id 0x100000355 ,已注册,匹配,有效          
        ,忙0 (43 ms ),保留15 > //端口2  

您可以看到@ 0和@ 1仅有两个端口(我删除了第三个端口,因为它从睡眠中唤醒后会导致延迟)

因此,从逻辑上讲,@ 0表示LVDS,@ 1表示端口0105,@ 2表示端口0204。

修补程序以删除未使用的连接器:

众所周知,我们在端口0204上使用HDMI,而端口0000是内部LVDS,我们可以摆脱不需要的端口0105。

我们将用0204替换端口0105,并使端口0204无效。为此的补丁是:

名称:AppleIntelFramebufferAzul

查找: 01050900 00040000 87000000 02040900

代表: 02040900 00040000 87000000 FF000000

HDMI修补程序:

您将必须使用IOREG来识别用于HDMI的端口。您将看到“ AppleDisplay”,就像在LVDS的帧缓冲区0下看到“ AppleBacklightDisplay”一样。

一旦确定了用于HDMI的端口,您只需将其连接器类型更改为0008

HDMI端口0204的补丁为:

名称:AppleIntelFramebufferAzul

查找:02040900 000 4 0000 87000000

代表:02040900 000 8 0000 87000000

请注意,现在我们仅在以上补丁中更改了连接器类型。

DvMT补丁(仅适用于Haswell或更低版本,BDW +动态确定DvMT):

我们知道,默认情况下,我们的platform-id使用32MB DvMT。在PC上,我们可以修改此值。假设我在BIOS中将DvMT设置为64MB,那么,我必须修补Framebuffer才能利用它。

首先,我们需要将64MB值转换为Intel字节格式,例如:

64 1024 1024 = 67108864(十进制)

现在我们需要将其转换为十六进制格式。所以:

67108864 = 0x4000000(十六进制)

现在将其转换为英特尔字节格式:

0x4000000 = 00000004

现在我们知道需要将DvMT值替换为00000004。为此的补丁是:

名称:AppleIntelFramebufferAzul

查找:0600260A 01030303 000000 02

代表:0600260A 01030303 000000 04

注意: 帧缓冲区值+游标字节数必须小于DvMT值,否则会出现内核崩溃。

修补游标字节和FrameBuffer大小:

如您所知,在某些情况下,我们必须将光标字节更改为9MB,以修复一些计算机上的菜单栏故障。您也可以将帧缓冲区修补为其他大小。只要记住上面的注释,FB + CB。

将光标字节更改为48MB,将帧缓冲区更改为48MB的简单补丁是:

名称:AppleIntelFramebufferAzul

查找:0600260A 01030303 00000002 00003001 00006000

代表:0600260A 01030303 00000002 00000003 00000003

但是,您可以看到48 + 48 = 96MB,这比我们的DvMT大32MB。因此,我们需要将DvMT值调整为等于或大于96MB。我将以128MB为例。

因此,最终补丁将是:

名称:AppleIntelFramebufferAzul

查找:0600260A 01030303 00000002 00003001 00006000

代表:0600260A 01030303 00000008 00000003 00000003

一般注意事项:

最好将不同的补丁合并为一个补丁,因为这样可以减少冲突的机会。
如果要在某些修补程序中更改端口号,则其他修补程序应遵循该值。例如,如果将端口设置为2,然后在DvMT补丁程序中将端口计数设置为3,则很可能会引起恐慌。

如何将多个补丁合并为一个:

我将使用一个补丁来更改端口数,DvMT,帧缓冲区和光标字节。让我们看一下:

名称:AppleIntelFramebufferAzul

找到:0600260A 0103 0303 00000002 00003001 00006000

代表:0600260A 0103 0303 00000008 00000003 00000003

在上述补丁中我做了什么?您可能已经知道,0x0a260006具有3个端口,具有32MB DvMT,19MB帧缓冲区和6MB游标字节。

我将端口数更改为2,将DvMT更改为128MB,将帧缓冲区和光标字节更改为48MB。

Broadwell的样本数据:

06002616 01030303 00002002 00005001->平台ID,端口,帧缓冲区,游标字节。您可能会注意到,没有DvMT,因为它是动态确定的。

提示:您可以看到小于32MB的帧缓冲区+光标字节(34 + 21 = 55)。因此证明,在Broadwell或更高版本上,DvMT必须设置为64MB或更大。否则,您将无法启动macOS安装程序。

如果您无法在BIOS中更改DvMT,则可以通过EFI Shell或BIOS改装来完成。如果您不能这样做,则可以使用Lilu + IntelGraphicsDvMTFixup来解决此问题。

虽然,IntelGraphicsDvMTFixup可能会让您进入安装程序,也可能使您能够使用macOS,但是当您修补帧缓冲区时,事情会变得很麻烦,因为IntelGraphicsDvMTFiFixup严重依赖于帧缓冲区数据。如果更改它,它将不会加载,因此会出现恐慌。

因此,请考虑一种解决方法。知道了吗?是的,更改FrameBuffer和Cursor Bytes值,使其小于或等于DvMT。

大多数PC的DvMT设置为32MB。而且,如果您仔细阅读本指南,就会知道Haswell可以使用32MB的prealloc很好。因此,普通人会为Broadwell或更高版本复制相同的补丁。但是有一个问题。当使用默认的haswell数据时,您有19MB作为帧缓冲区和6MB作为光标字节。

但是,如果您在Broadwell上使用相同的数据(特别是6MB的光标字节),则可以启动macOS,但可能会出现随机故障,主要是在菜单栏中。

因此,我们将使用9MB作为游标字节。我们可以看到19 + 9 = 28MB,小于所需的DvMT(32MB)值。

因此,对此的补丁将是:
名称:AppleIntelBDWGraphicsFramebuffer
查找:06002616 01030303 00002002 00005001
代表:06002616 01030303 00003001 00009000

希望您有想法,并可以根据需要遵循本指南。如果您遇到困难,OSXL可以满足您的需求。

感谢Pike,RehabMan和其他许多人对此事的初步研究。

干杯

跟贴者:

https://pikeralpha.wordpress.com/2013/06/24/haswell-cpuigpu-power-management-with-a-ga-z87m-d3h/

https://pikeralpha.wordpress.com/2013/06/27/appleintelframebufferazul-kext/

https://pikeralpha.wordpress.com/2013/08/02/appleintelframebufferazul-kext-part-ii/

https://pikeralpha.wordpress.com/2013/09/25/appleintelframebufferazul-kext-part-iii/

0600260A 01 030303 00000002 00003001 FB id /移动/管道|端口| FBMem-Count / StolenMem / FBMem 00006000 00000060 D90A0000 D90A0000 CursorMem / RAM / Freq / MaxFreq 00000000 00000000 00 00 08 00 0200 0000 f b索引 /端口号/ 管道

30000000 01 05 09 00 00040000 87000000 连接器类型/ 标志
02 04 09 00 00040000 87000000 FF000000
01000000 40000000 0F000000 01010000

04000000 00000000 0E000000 00000000

0600260A->布局ID
01 03 03 03->移动+ nb的管道+ nb的端口+ nb的帧缓冲区
00000002-> fStolenMemorySize(= BIOS分配):0x02000000 = 32MB
00003001-> fFramebufferMemorySize:0x01300000 = 19MB
00006000-> fCursorBytes:0x00060000 = 6MB
00000060->最大值 VRAM:0x06000000 = 1536MB
D90A0000-> f背光频率
D90A0000-> fBacklightMaxFrequency
00000000
00000000
00 00 0800 02000000 30000000-> FB索引0 +端口#0 +管道属性+ LVDS连接器类型+激活延迟(标志)
01 05 0900 00040000 87000000-> FB索引1 +端口#5 +管道属性+ DP连接器类型+激活延迟(标志)
02 04 0900 00040000 87000000-> FB索引2 +端口#6 +管道属性+ DP连接器类型+激活延迟(标志)

从那里开始,可能会有不同的二进制补丁:

显示输出端口数
输出端口索引(FB#+端口号)
输出端口连接器类型
最大限度。虚拟RAM

这些修补原理-我想强调“原理”一词-对于Ivy Bridge,Haswell,Broadwell framebuffer kext是可重复的。

现有指南已针对以下方面发布:

桑迪桥HD3000图形
常春藤桥HD4000图形
Haswell HD4x00 / HD5000 / Iris图形

任何希望修补适用于他/她自己的计算机的帧缓冲区扩展的人都应该:

识别iGPU的相关帧缓冲区kext(用于HD3000的SNB,用于HD4000的Capri,用于Haswell的Azul,用于Broadwell的BDW)
识别iGPU的相关布局ID(Clover Configurator应用程序将它们全部列出,以供参考;否则,敏锐的人们可能会使用Hex编辑器在kext的二进制文件中查找表)
标识您需要/想要打补丁的输出端口(使用IOReg数据确定端口)
应用相关补丁(例如:将HDMI的连接器类型更改为0008 0000)

在以上线程中已对样本进行了详细说明。

先引入类IOFactory.php

require_once '../PHPExcel/IOFactory.php';
$filePath = "test.xlsx";  // 测试文件

加载测试文件

$inputFileType = PHPExcel_IOFactory::identify($filePath) 判断文件类型
$objReader = PHPExcel_IOFactory::createReader($inputFileType); 实例化类型对象
$objPHPExcel = $objReader->load($filePath); 加载文件

下面主要判断Excel2007和Excel5类型,即xlsx/xlsm/xltx/xltm和xls/xlt格式文件

try {
    $inputFileType = PHPExcel_IOFactory::identify($filePath);
    if ($inputFileType !== "Excel5" && $inputFileType !== "Excel2007" ) {
        unlink($filePath) && str_alert(-1,"请确保导入的文件格式正确!");
    }
    $objReader = PHPExcel_IOFactory::createReader($inputFileType);
    $objPHPExcel = $objReader->load($filePath);
} catch(Exception $e) {
    unlink($filePath) && str_alert(-1,'加载文件发生错误:”'.pathinfo($filePath,PATHINFO_BASENAME).'”: '.$e->getMessage());
    }

获取当前工作表

$sheet = $objPHPExcel->getSheet(0);
//或者
$sheet = $objPHPExcel->getActiveSheet();

获取工作表行数和列数

$highestRow = $sheet->getHighestRow();
$highestColumn = $sheet->getHighestColumn();

注意:有时候你会发现你的表格明明有内容的行数就5行,但是获取到的$highestRow却有7,8行或者更多,这可能是因为你在操作你的表格的时候不小心点击了其它行数,虽然没有填写内容,但getHighestRow也是能够识别出行数;
想要获取有内容的行数应该使用getHighestDataRow和getHighestDataColumn
源码注释是这样介绍的string Highest row number that contains data,即包含数据的字符串最高行数.

单元格具体内容
xlsx类型的表格单元格是通过类似xy轴坐标来获取的,

可通过类似

 $sheet->getCell("A1")->getValue();
 $sheet->getCell("B2")->getValue();

获取相应位置的内容,
如果不想通过字母了来遍历获取,可以用数字索引方法

  $sheet->getCellByColumnAndRow(0,1);
  $sheet->getCellByColumnAndRow(1,2);

注意坐标中第一个参数从0开始,0代表A,1代表B...,第二个参数从1开始.
下面是遍历表格获取全部单元格内容:

$dataSet=array();
for ($column = "A"; $column <= $highestColumn; $column++) {//列数是以A列开始
    for ($row = 4; $row <= $highestRow; $row++) { //行数是以第4行开始
        $cell = $sheet->getCell($column . $row)->getValue();
        if($cell instanceof PHPExcel_RichText) { //富文本转换字符串
            $cell = $cell->__toString();
        }
        $dataSet[$row][] = $cell;
    }
}

其中富文本转换字符串,是使用$cell instanceof PHPExcel_RichText判断是否为富文本,查阅资料发现如果你的单元格中字符串包含两种以上的字体会自动被设为富文本,这时候需要__toString()转换

判断合并单元格是否位于最左上角
当我们循环输出所有单元格后发现,一些被合并的单元格只有最左上坐标的是有内容的,其他都是null
例如A4,A5合并成一个单元格,getCell("A4")是有正常内容的,但是getCell("A5")是null.
isMergeRangeValueCell可以用来判断某个具体的单元格是否为最左上角

$sheet->getCell('A' . $row)->isMergeRangeValueCell()

当$row为4的时候是返回true,5的时候返回false

转换时间格式的处理
获取表格中时间格式的内容,需要PHPExcel_Shared_Date::ExcelToPHP()来转换为php可识别的时间格式

date('Y-m-d',PHPExcel_Shared_Date::ExcelToPHP($sometime);


//例子
$cell = $sheet->getCell($column . $row)->getValue();
//日期格式判断
if (is_float($cell)) {
    $date = gmdate('Y-m-d', PHPExcel_Shared_Date::ExcelToPHP($cell));
} elseif (preg_match("/(\d{4}\/\d{1,2}\/\d{1,2}|\d{4}-\d{1,2}-\d{1,2})/", $cell)) {
    $date = zmf::time(strtotime($cell), 'Y-m-d');
} else {
    return $this->jsonOutPut(0, "第{$row}行数据日期格式不正确,请确认");
}

最近数据库服务器多事之秋,莫名的批量宕机事件一再发生,搞得压力超大。厂商来了之后也酥手无策。上周路过寺庙,平生第一次感叹道是否要去烧烧香,拜托拜托数据库之神能让我们团队早日度过这个劫难。

上周和William聊到MySQL的参数sql_slave_skip_counter,感叹很多人并没有真正了解这个参数的含义。面试时这是一个很好的问题,相信即使是淘宝P7的level,要准确答对这个问题也是需要平时的细心累积。

01

很多同学的误区在于会把参sql_slave_skip_counter=N理解成跳过N个事务。如果这样的回答,至少在我心中已经扣分不少,要拿高P几乎不可能。首先看看文档中的定义:

SET GLOBAL sql_slave_skip_counter = N

This statement skips the next N events from the master. This is useful for recovering from replication stops caused by a statement.

官方文档中明确指出N表示的是N个event。很多同学把这个参数的单位理解成事务的原因在于他把操作都理解成了由单条语句所组成的事务。这时N的含义两者等价。

然而,更常见的场景却是一个事务可能由多个EVENT组成,例如一个事务可以有多个SQL组成,例如:

BEGIN; INSERT ...;DELETE ...; INSERT; COMMIT;

若这时将N理解成事务,那么结果就会非常不同。当然,答对参数sql_slave_skip_counter的单位是事务,这个答案也仅只有60分。

02

如果细看文档的话,文档最后一段还说道:

When you use SET GLOBAL sql_slave_skip_counter to skip events and the results in the middle of a group, the slave continues to skip events until it reaches the end of the group. Execution then starts with the next event group.

这句非常关键,也就是说可能上面的答案是:以上全错。N可以不表示跳过N个事务,甚至可能是跳过>=N个事务的场景。假设开始时主、从的数据分别为:

Master

Slave
a
1
2
3

+----+ +----+

a
1
3

由于主从数据已然不一致,这时若在主上执行下面的SQL:

BEGIN;

INSERT INTO Z SELECT 4;

DELETE FROM Z WHERE a = 2;

INSERT INTO Z SELECT 5;

COMMIT;

从机显然会报错,提示1032错误,因为记录2这条记录并没有找到。这时的处理方法很多DBA会选择执行SET GLOBAL sql_slave_skip_counter=1。然而,这样的处理会导致INSERT 5这条记录不被执行。因为跳过DELETE 2这个操作后,事务没有结束,会继续跳过接下去的event,这就是文档中说的:the slave continues to skip events until it reaches the end of the group。感兴趣的同学可以自行测试看看最终的结果。

若只想跳过一个EVENT该怎么做呢?其实,只需将参slave_exec_mode设置为IDEMPOTENT即可。

03

出现主从复制出错,最安全的方法还是重建从机。另外,MySQL的复制早就是crash safe的复制机制了。若你的复制环境经常出错,应该好好检查下数据库的配置参数。

对于参数sql_skip_slave_counter来说,这只是一个不得已为之的方法。同时,当开启GTID模式时,也无法通过参数进行跳过出错的EVENT。

原文:https://mp.weixin.qq.com/s/rZZbLmN0Klq0o0bvnijizw

解决python pip 安装报语法错误sys.stderr.write(f“ERROR: {exc}“)

https://bootstrap.pypa.io/ 下载相应python版本的 get-pip.py 文件

wget https://bootstrap.pypa.io/2.7/get-pip.py
python get-pip.py

安装成功:Successfully installed pip-20.3.4 wheel-0.36.2

再运行我想要的bt系统,结果报错了

# bt start
Starting Bt-Panel... failed
------------------------------------------------------
Traceback (most recent call last):
  File "main.py", line 16, in <module>
    import sys,web,io,os
ImportError: No module named web
------------------------------------------------------
Error: BT-Panel service startup failed.

原因是web.py模块没有安装,用pip安装试试, 还是报错,不过这次是不一样的错误,原因是6.10的系统2.7的python需要安装指定版本的web.py

pip install web.py==0.51

结果成功,bt也成功运行起了

PS:测试环境 centos 6.10, python 2.7

安装脚本setuptools:

wget https://bootstrap.pypa.io/ez_setup.py -O - | python