进程资源图理解与化简

一 了解进程资源图

二 化简资源分配图


方法步骤
  • 第一步:先看系统还剩下多少资源没分配,再看有哪些进程是不阻塞(“不阻塞”即:系统有足够的空闲资源分配给它)的
  • 第二步:把不阻塞的进程的所有边都去掉,形成一个孤立的点,再把系统分配给这个进程的资源回收回来
  • 第三步:看剩下的进程有哪些是不阻塞的,然后又把它们逐个变成孤立的点。
  • 第四步:最后,所有的资源和进程都变成孤立的点。这样的图就叫做“可完全简化”。

如果一个图可完全简化,则不会产生死锁;如果一个图不可完全简化(即:图中还有“边”存在),则会产生死锁。这就是“死锁定理”。 

实例

解析:

R1有两个资源,一个分配给了P1,一个分配给了P3,此时P2申请R1的资源,因为R1此时没有可用资源,P2堵塞。

R2有三个资源,已经给P1,P2,P3,各自分配了一个资源,而P1此时又再次申请资源R2,P1堵塞

R3有两个资源,已经分配给P2一个,P2申请一个资源,分配给它,所以P3是非阻塞结点

化简的话,看从没有阻塞的结点开始,删去P3周围所有的边,使其成为一个孤立的点,然后看剩下的资源按上述步骤再次进行分配,若到最后只剩下一群孤立的点,则说明该资源图是可以化简的。

参考链接


进程资源图理解与化简

Visual Studio Code调试Flutter报错“[CHROME]:need to run as root or suid”

在最新的 Ubuntu 22.04 系统上使用Visual Studio Code调试Flutter应用,Chrome使用Snap安装。

通过指定 CHROME_EXECUTABLE=/snap/bin/chromium,在调试的时候,报错如下:

Launching lib/main.dart on Chrome in debug mode...
lib/main.dart:1
[CHROME]:need to run as root or suid
Failed to launch browser after 3 tries. Command used to launch it: /snap/bin/chromium --user-data-dir=/tmp/flutter_tools.SEVTFD/flutter_tools_chrome_device.AMHTFX --remote-debugging-port=38457 --disable-background-timer-throttling --disable-extensions --disable-popup-blocking --bwsi --no-first-run --no-default-browser-check --disable-default-apps --disable-translate http://localhost:42407
Failed to launch browser. Make sure you are using an up-to-date Chrome or Edge. Otherwise, consider using -d web-server instead and filing an issue at https://github.com/flutter/flutter/issues.
Exited (sigterm)

解决方法就是指定真实的Chrome安装路径,直接调用,而不是通过Snap的沙箱,解决沙箱无法调试的问题。

如下:

#export CHROME_EXECUTABLE=/snap/bin/chromium
export CHROME_EXECUTABLE=/snap/chromium/current/usr/lib/chromium-browser/chrome

上述方法同样可以解决 Android Studio 在 Ubuntu 22.04 系统上无法找到 Chrome 的问题。

参考链接


How to get the snap-based chromium to access a separately mounted filesystem?

SSH默认不支持RSA了

今天升级ubuntu 22.04/Window 11后最基本的ssh登陆突然出问题了, 提示有几种:

Unable to negotiate with UNKNOWN port 65535: no matching host key type found. Their offer: ssh-rsa,ssh-dss
lost connection

sign_and_send_pubkey: no mutual signature supported
Git Pull failed
  Unable to negotiate with xx.xx.xx.xx port 22: no matching host key type found. Their offer: ssh-rsa,ssh-dss
   Could not read from remote repository.
   Please make sure you have the correct access rights
   and the repository exists.

一查发现…好嘛, openssh觉得ssh-rsa加密方式不安全, 直接从8.8开始默认不允许这种密钥用于登陆了

解决方法是可以在~/.ssh/config里面加这么一段解决:

Host *
    PubkeyAcceptedKeyTypes +ssh-rsa
    HostKeyAlgorithms +ssh-rsa

第一行说明对所有主机生效, 第二行是将 ssh-rsa 加会允许使用的范围, 第三行是指定所有主机使用的都是 ssh-rsa 算法的key

实测两行都得要写才行, 没有第二行提示没有 ssh-rsa 这么个类型

没有第三行就提示 sign_and_send_pubkey: no mutual signature supported

参考链接


ssh默认不支持rsa了

解决远程桌面执行sudo启动X应用报错“Gtk-WARNING **: 12:39:47.296: cannot open display: :10.0”

通过远程桌面(RDP)连接到远程Ubuntu服务器桌面,执行调用X窗口应用的时候,报错如下:

$ sudo update-manager
No protocol specified
Unable to init server: Could not connect: Connection refused
No protocol specified
Unable to init server: 无法连接: Connection refused
No protocol specified
Unable to init server: 无法连接: Connection refused

(update-manager:2547): Gtk-WARNING **: 12:39:47.296: cannot open display: :10.0

原因因为:
XServer默认情况下不允许别的用户的图形程序的图形显示在当前屏幕上

如果需要别的用户的图形显示在当前屏幕上,则应以当前登陆的用,也就是切换身份前的用户执行如下命令。

当前登陆普通用户执行:xhost +

$ xhost +
access control disabled, clients can connect from any host

$ sudo update-manager

参考链接


Ubuntu gedit报错Gtk-WARNING **: cannot open display: 问题解决

佳能打印机MG3600 Series重新配置Wi-Fi

重要事项

  • 设备通过无线路由器连接到互联网时,如果将其连接到处于直接连接模式的打印机,设备和无线路由器之间的现有连接将被禁用。 在这种情况下,根据设备的不同,设备连接可能会自动切换至移动数据连接。 当使用移动数据连接连接到互联网时,根据合同,可能会产生费用。

(出现在一个新窗口中)

  1. 如果打印机上的Wi-Fi指示灯(A)闪烁,按停止按钮(B)。

  2. 按住打印机上的Wi-Fi按钮(C)直至电源指示灯(D)闪烁。

  3. 按彩色按钮(E),然后按Wi-Fi按钮(C)。

  4. 确保Wi-Fi指示灯快速闪烁且电源指示灯亮起。

  5. 请返回应用程序屏幕继续进行设置。

  6. 手机上安装 “佳能打印”软件,然后搜索经过上述操作后,新出现的Wi-Fi热点,然后根据说明操作。

  7. 如果配置打印机连接的路由器,启用了 “Wi-Fi多频合一”(比如:TP-Link ) 则会出现无法在 “佳能打印”软件上输入 SSID 的密码的情况。这种情况下,需要在配置的时候,暂时关闭 “Wi-Fi多频合一”。在配置完成后,可以打开 “Wi-Fi多频合一” 。

参考链接


安装指南- MG3600 series -

Android/iOS手机朝向获取

对于iOS手机:

苹果公司给出了一个枚举,如下:

 typedef NS_ENUM (NSInteger, UIDeviceOrientation) {
    UIDeviceOrientationUnknown,
    UIDeviceOrientationPortrait,            // 竖向,home键向下
    UIDeviceOrientationPortraitUpsideDown,  //  竖向,home键向上
    UIDeviceOrientationLandscapeLeft,       // 横向,home键向右
    UIDeviceOrientationLandscapeRight,      //  横向,home键向左
    UIDeviceOrientationFaceUp,              // 屏幕平放,向上
    UIDeviceOrientationFaceDown             // 屏幕平放,向下
}
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {

    UIInterfaceOrientationUnknown            = UIDeviceOrientationUnknown,

    UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,

    UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,

    UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,

    UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft

}

2、对于获取手机屏幕
(1)

[[ UIDevice currentDevice ] beginGeneratingDeviceOrientationNotifications ];
    dispatch_async ( dispatch_get_main_queue (), ^{
        NSLog ( @"=========%zd" ,[[ UIDevice currentDevice ] orientation ]);
    });
    [[ UIDevice currentDevice ] endGeneratingDeviceOrientationNotifications ];

(2)

UIInterfaceOrientation orientation = [ UIApplication sharedApplication ]. statusBarOrientation ;

3、对于当前手机是不是横屏或者竖屏的判断
(1)判断是否是竖屏

static inline BOOL UIDeviceOrientationIsPortrait( UIDeviceOrientation orientation) {
    return ((orientation) == UIDeviceOrientationPortrait || (orientation) == UIDeviceOrientationPortraitUpsideDown );
}

(2)判断是否是横屏

static inline BOOL UIDeviceOrientationIsLandscape( UIDeviceOrientation orientation) {
    return ((orientation) == UIDeviceOrientationLandscapeLeft || (orientation) == UIDeviceOrientationLandscapeRight );
}
对于Android手机:
public class SimpleOrientationActivity extends Activity {
    OrientationEventListener mOrientationListener;
  
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        mOrientationListener = new OrientationEventListener(this,
            SensorManager.SENSOR_DELAY_NORMAL) {
 
            @Override
            public void onOrientationChanged(int orientation) {
                Log.v(DEBUG_TAG,
                    "Orientation changed to " + orientation);
            }
        };
 
       if (mOrientationListener.canDetectOrientation()) {
           Log.v(DEBUG_TAG, "Can detect orientation");
           mOrientationListener.enable();
       } else {
           Log.v(DEBUG_TAG, "Cannot detect orientation");
           mOrientationListener.disable();
       }
    }
 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mOrientationListener.disable();
    }
}

判断手机方向的具体判断代码如下:

if (OrientationEventListener.ORIENTATION_UNKNOWN == orientation) { 
    return; //手机平放时,检测不到有效的角度 
}

// 我们只关心 0, 90, 180 ,270 测试发现,很多设备返回的数据是很混乱的,但是这四个度数比较稳定
if((0 == orientation % 90) && (orientation < 360) && (orientation >= 0)) {
    //只检测是否有四个角度的改变
    if (orientation > 350 || orientation < 10) { //0度
        orientation = 0;
    } else if (orientation > 80 && orientation < 100) { //90度
        orientation = 90;
    } else if (orientation > 170 && orientation < 190) { //180度
        orientation = 180;
    } else if (orientation > 260 && orientation < 280) { //270度
        orientation = 270;
    } else {
        return;
    }
    Log.i("MyOrientationDetector ", "onOrientationChanged:" + orientation);
}
对于 Flutter:

使用 native_device_orientation 插件完成相同的检测功能。

参考链接


Flutter找不到Android模拟器解决

Flutter配置好后,在Android Studio中找不到设备

完成Flutter的Android配置之后,连上设备,运行flutter doctor,发现已经识别了一个可用设备了

[✓] Connected device (1 available)

但是用Android Studio新建Flutter项目之后,却一直显示未找到设备。

No connected devices found; please connect a device, or see flutter.io/setup for getting started ins

最后在Stack Overflow上找到了解决方案:

https://stackoverflow.com/questions/49222658/device-list-doesnt-shows-in-android-studio-using-flutter

就是要配置一下flutter关联的Android sdk路径和Android Studio文件夹,我的设置完sdk路径就可以正常找到device了,问题解决~。

粗体部分替换成自己的Android sdk路径:

flutter config --android-sdk /path/to/android/sdk

粗体部分替换成自己的android studio文件夹路径(我的不用配置这个就成功了):

flutter config --android-studio-dir /path/to/android/studio

注意,上面的操作在重启之后无效,如果希望重启之后也生效,则编辑 ~/.flutter_settings ,增加如下配置即可:

android-sdk=/path/to/android/sdk

参考链接


LocalAuthentication开发实践

在iPhone 5s加入Touch ID后,指纹识别的功能在App中逐渐受到青睐,特别是对于本地安全较高的应用(如带支付的App)指纹识别是必备的功能,它既能解决在验证过程中输入密码的繁琐过程,同时指纹识的安全等级更高。那么,要想在自己开发的应用中使用指纹识别,就必须要LocalAuthentication.framework提供的API,下面将详细地介绍如何使用这个框架来实现指纹识别功能。

基础用法

我们先来看下面的例子:

LAContext *context = [[LAContext alloc] init];
    
NSError *error = nil;
if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error])
{
    [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"输入指纹进行验证" reply:^(BOOL success, NSError * _Nullable error) {
            
        if (success)
        {
            NSLog(@"验证成功");
        }
        else
        {
            NSLog(@"验证失败");
        }

    }];
}
else
{
    NSLog(@"识别功能不可用");
}

继续阅读LocalAuthentication开发实践

移动端系统生物认证技术详解

相信大家对于生物认证应该不会陌生,使用指纹登陆或者 FaceId 支付等的需求场景如今已经很普遍,所以基本上只要涉及移动端开发,不管是 Android 、iOS 或者是 RN 、Flutter 都多多少少会接触到这一业务场景。

当然,不同之处可能在于大家对于平台能力或者接口能力的熟悉程度,所以本篇主要介绍 Android 和 iOS 上使用系统的生物认证需要注意什么,具体流程是什么,给需要或者即将需要的大家出一份汇总的资料

继续阅读移动端系统生物认证技术详解