三十三、Swoole 基础学习笔记 - Swoole 系统 API

作者: 温新

分类: 【Swoole 系列】

阅读: 1525

时间: 2023-03-13 12:20:15

hi,我是温新,一名PHPer

文章基于 Swoole 5.0.1 版本编写。

学习目标:了解系统 API

说明:本篇文章结合官方文档编写及参考网络资料编写,虽非全部原创,但也是结合了自己的理解,若转载请附带本文 URL,编写不易,持续编写更不易,谢谢!

Coroutine\System 系统相关 API 的协程封装。大部分 API 基于 AIO 线程池实现。

官方推荐使用Co\System::sleepSwoole\Coroutine\System::sleep

statvfs

含义:获取文件系统信息。

语法:

Swoole\Coroutine\System::statvfs(string $path): array|false

# 参数
$path:文件系统挂载的目录【如 /,可以使用 df 和 mount -l 命令获取】

案例:

Swoole\Coroutine\run(function () {
    print_r(Swoole\Coroutine\System::statvfs('/usr/local/src'));
});

输出结果:

$php 33-swoole-system-api.php 
Array
(
    [bsize] => 4096
    [frsize] => 4096
    [blocks] => 51328506
    [bfree] => 41599890
    [bavail] => 38974354
    [files] => 13107200
    [ffree] => 12521751
    [favail] => 12521751
    [fsid] => 3942528374396710653
    [flag] => 4096
    [namemax] => 255
)

fwrite

含义:协程方式向文件写入数据。

语法:

Swoole\Coroutine\System::fwrite(resource $handle, string $data, int $length = 0): int|false
    
# 参数
$handle:文件句柄【必须是 fopen 打开的文件类型 stream 资源】
$data:要写入的数据内容【可以是文本或二进制数据】
$length:读取的长度【默认为 0,表示写入 $data 的全部内容,$length 必须小于 $data 的长度】

案例:

$fp = fopen('test.txt', 'a+');
Swoole\Coroutine\run(function () use ($fp) {
    $result = Swoole\Coroutine\System::fwrite($fp, '我叫王美丽');
    var_dump($result);
});
fclose($fp);

fread

含义:协程方式读取文件。

语法:

Swoole\Coroutine\System::fread(resource $handle, int $length = 0): string|false

# 参数
$handle:文件句柄【必须是 fopen 打开的文件类型 stream 资源】
$length:读取的长度【默认为 0,表示读取文件的全部内容】

返回值:读取成功返回字符串内容,读取失败返回 false

案例:

$fp = fopen('test.txt', 'r');
Swoole\Coroutine\run(function () use ($fp) {
    $result = Swoole\Coroutine\System::fread($fp);
    // 读取的长度为字节
    // $result = Swoole\Coroutine\System::fread($fp, 3);
    var_dump($result);
});
fclose($fp);

fgets

含义:协程方式按行读取文件内容。

说明:底层使用了 php_stream 缓存区,默认大小为 8192 字节,可使用 stream_set_chunk_size 设置缓存区尺寸。

语法:

Swoole\Coroutine\System::fgets(resource $handle): string|false
    
# 返回值
读取到 EOL(\r 或 \n)将返回一行数据,包括 EOL;
未读取到 EOL,但内容长度超过 php_stream 缓存区 8192 字节,将返回 8192 字节的数据,不包含 EOL;
达到文件末尾 EOF 时,返回空字符串,可用 feof 判断文件是否已读完;
取失败返回 false。

案例

$fp = fopen('test.txt', 'r');
Swoole\Coroutine\run(function () use ($fp) {
    while (!feof($fp)) {
        echo Swoole\Coroutine\System::fgets($fp) . PHP_EOL;
    } 
});
fclose($fp);

readFile

含义:协程方式读取一个文件的内容。

语法:Swoole\Coroutine\System::readFile(string $filename): string|false

案例:

$file = 'test.txt';
Swoole\Coroutine\run(function () use ($file) {
    $result = Swoole\Coroutine\System::readFile($file);
    print_r($result);
    $content = Swoole\Coroutine\System::readFile('test.txt');
    print_r($content);
});

writeFiel

含义:协程方式写入文件。

语法:

Swoole\Coroutine\System::writeFile(string $filename, string $fileContent, int $flags): bool

# 参数
$filename:文件名【必须有可写权限,文件不存在会自动创建。打开文件失败会立即返回 false】;
$fileContent:写入到文件的内容【最大可写入 4M】;
$flags:写入的选项【默认会清空当前文件内容,可以使用 FILE_APPEND 表示追加到文件末尾】

案例:

Swoole\Coroutine\run(function () {
    $content = Swoole\Coroutine\System::writeFile('baidu.txt', file_get_contents('https://www.baidu.com'));
    var_dump($content);
});

sleep

含义:进入等待状态。

说明:相当于 PHP 中的 sleep 函数,不同的是 Coroutine::sleep 是协程调度器实现的,底层会 yield 当前协程,让出时间片,并添加一个异步定时器,当超时时间 到达时重新 resume 当前协程,恢复运行。使用 sleep 接口可以方便地实现超时等待功能。

语法:

Swoole\Coroutine\System::sleep(float $seconds): void
# 参数
$seconds:睡眠的时间【必须大于 0,最大不得超过一天时间(86400 秒)】

exec

含义:执行一条 sheel 指令。底层自动进行协程调度。

语法:Swoole\Coroutine\System::exec(string $cmd): array

案例:

Swoole\Coroutine\run(function() {
    $ret = Swoole\Coroutine\System::exec('ls');
    print_r($ret);
});

gethostbyname

含义:将域名解析为 IP。

语法:

Swoole\Coroutine\System::gethostbyname(string $domain, int $family = AF_INET, float $timeout = -1): string|false

# 参数
$domain:域名;
$family:域族;
$timeout:超时时间

案例:

Swoole\Coroutine\run(function() {
    $ip = Swoole\Coroutine\System::gethostbyname('www.baidu.com');
    var_dump($ip);
});

输出结果:

$php 33-swoole-system-api.php 
string(13) "14.215.177.38"

getaddrinfo

含义:进行 DNS 解析,查询域名对应的 IP 地址。与 gethostbyname 不同,getaddrinfo 支持更多参数设置,而且会返回多个 IP 结果。

语法:

Swoole\Coroutine\System::getaddrinfo(string $domain, int $family = AF_INET, int $socktype = SOCK_STREAM, int $protocol = STREAM_IPPROTO_TCP, string $service = null, float $timeout = -1): array|false

# 参数
$domain:域名;
$family:域族【AF_INET 表示返回 IPv4 地址,使用 AF_INET6 时返回 IPv6 地址】;
$socktype :协议类型;
$protocol : 协议;
$service:
$timeout:超时时间

案例:

Swoole\Coroutine\run(function() {
    $ret = Swoole\Coroutine\System::getaddrinfo('www.baidu.com');
    var_dump($ret);
});

输出结果:

$php 33-swoole-system-api.php 
array(2) {
  [0]=>
  string(13) "14.215.177.38"
  [1]=>
  string(13) "14.215.177.39"
}

wait

含义:对应原有的 Process:wait,不同的是此 API 是协程版本,会造成协程挂起,可替换 Swoole\Process::waitpcntl_wait 函数。

语法:Swoole\Coroutine\System::wait(float $timeout = -1): array|false

每个子进程启动后,父进程必须都要派遣一个协程调用 wait()(或 waitPid()) 进行回收,否则子进程会变成僵尸进程,会浪费操作系统的进程资源。 如果使用了协程,必须是先创建进程,进程里面再开协程。而不是反过来,否则就是带着协程 fork 情况会非常复杂,导致底层很难处理。

waitPid

含义:和上述 wait 方法基本一致,不同的是此 API 可以指定等待特定的进程。

语法:

Swoole\Coroutine\System::waitPid(int $pid, float $timeout = -1): array|false
    
# 参数
$pid:进程 id

案例:

$process = new Swoole\Process(function () {
    echo 'Hello Swoole' . PHP_EOL;
});
$process->start();

Swoole\Coroutine\run(function () use ($process) {
    $status = Swoole\Coroutine\System::waitPid($process->pid);
    print_r($status);
});

输出结果:

$php 33-swoole-system-api.php 
Hello Swoole
Array
(
    [pid] => 34944
    [code] => 0
    [signal] => 0
)

我是温新,本篇文章结束。

请登录后再评论