20210430のLinuxに関する記事は10件です。

LPIC304チートシート

xlコマンド vcpu-list…cpu情報 vcpu-set…cpu設定 xen vif…IP,MAC設定 dom0_mem は grub.cfg に設定 ハイパーバイザ…独立とリソースマッピング保証 qemu-kvmコマンド -name…VMの名前指定 -boot…ブートデバイス指定 -cdrom…ISOをVMに -monitor stdio…QEMU標準出力 -net user…userモード -net tap…TUN/TAP使用し、接続 -net nic…VLAN接続用NIC作成 qemu-imgコマンド info…イメージ情報 QEMUモニタ change…disk入替 info cpus…cpu情報 info network…net情報 info snapshots…SN一覧 高可用 DSR…LB経由せず直接レスポンス パワーフェンシング…障害ノード電源OFF スイッチフェンシング…通信を遮断 RPO…どの時点まで復旧? RTO…いつまでに復旧? LB nanny…リアルサーバを監視 LVSアルゴリズム rr…均等に wrr…処理能力に応じて均等に lc…少ない所に多く wlc…デフォルト、最小に多く、処理能力の重みづけを付加 ldlc…IP参照、少ない所に多く ldlcr… dh…宛先ハッシュ sh…送信元ハッシュ sed…最小遅延 nq…処理してないとこに→最小遅延 ipvsadmコマンド --start-deamon…デーモン開始 --stop-deamon…デーモン停止 -g,--gatewaying…ダイレクトルーティング -s,-scheduler…スケジューリング指定 keepalived…リアルサーバを監視、LB冗長化 virtual_server…仮想サーバ、LB delay_loop…監視感覚 lb_algo…アルゴリズム lb_kind…フォワーディング方式 VRRP…keepalivedで使われるLB冗長化 ldirectord…LVS設定を簡単に autoreload…設定ファイルが変わったら自動読み込み checkinterval…接続テスト間隔 checktimeout…応答がない時異常判定時間 checktype…チェック方法 fallback…全て停止した時の転送先 logfile…ログ保存先 quiescent…no=以上はリストから削除。yes=重みづけ0だけど削除しない real…リアルサーバとサービスの指定 HAproxy roundrobin…順番。重みづけ変更可 static-rr…順番。重みづけは静的 leastconn…コネクト少ない優先 source…送信元ハッシュ uri…uri全体をハッシュ化 url_param…URLパラメータによって振り分け hdr()…HTTPヘッダによって振り分け rdp-cookie…RDPクッキーにより振り分け /etc/haproxy/haproxy.cfgには最後にオプションを指定 pacemaker CIB…クラスタの設定、リソース状態 CRMd…クラスタ全体を管理 PEngine…CIBに基づいて最適化 LRMd…ローカルリソース管理 STONITHd…フェンシング cib.xml…CIBの内容、起動時自動作成される、クラスタと同期 RA…リソースエージェント LSB…内部構造標準仕様 OCF…LSB拡張、クラスタ標準 System Service…Systemd,Upstart,LSBの組み合わせ pacemaker関連コマンド crm_attribute…クラスタオプション管理 crm_mon…状態監視 crm_node…ノード情報一覧 crm_resouce…リソースタスク実行 crm_shadow…クラスタの前にサンドボックスで実行 crm_simulate…応答シミュ crm_stanby…crm_attributeのラッパー crm_verify…構文エラーチェック cibadminコマンド -C,--create…作成 -D,--delete…削除 -d,--delete-all…全て削除 -E,--erace…全てのコンテンツ削除 -M,--modify…変更 -o,--scope…操作の対象を限定 -Q,--query…検索 -R,--replace…置換 -u,--upgrade…設定を最新更新 -A,--xpath…XpathとしてXML指定 -l,--local…対象をローカルに -X,--xml-text…文字列としてXML指定 -x,--xml-file…XMLファイル指定 crmコマンド、crmshシェル cib…CIBの管理 cluster…クラスター管理 configure…CIB設定の管理 node…ノード管理 ra…リソースエージェント管理 resource…リソース管理 status…クラスタの状態表示 pcsコマンド acl…ACL設定 cluster…クラスタ、ノード設定 config…表示管理 constraint…リソース制約 property…プロパティ resource…リソース管理 status…状態表示 stonith…フェンスデバイス corosyncコマンド corosync-cfgtool…管理 corosync-cmapctl…DBアクセス corosync-keygen…認証キー生成 corosync-quorumtool…クオーラム設定、表示 DRBD…ミラーリング,drbd,/proc/drbd レプリーケーション A…非同期、障害に弱いけど早い B…メモリ同期、普通 C…同期、障害に強いけど遅い /etc/drbd.conf allow-two-primaries…デュアルプライマリで負荷分散 drbdadmコマンド -c,--config-file…設定ファイル指定 -s,--drbdsetup…drbdsetupの絶対パス -m,--drbdmeta…drbdmetaの絶対パス primary…プライマリに切り替え role…ロール表示、プライマリセカンダリ表示 syncer…再同期パラ読み込み verify…オンライン照合 cLVM…クラスタ内で論理Volumeを作る,clvmd vgsコマンド…一覧表示 vgchangeコマンド -a,--activate…アクティブ切替 -c,--cluster…VG共有するか? -l,--logicalvolume…LV最大 -p,--maxphysicalvolumes…PV最大 -s,--physicalextentsize…PVエクステントサイズ変更 GFSコマンド mkfs.gfs2…FS作成 mount.gfs2…FSマウント fsck.gfs2…check,修復 gfs2.grow…拡張 gfs2.edit…表示,出力,編集 gfs2.jadd…ジャーナル追加 OCFS2コマンド…/etc/ocfs2/cluster.conf mkfs.ocfs2…FS作成 mount.ocfs2…FSマウント fsck.ocfs2…check,修復 tunefs.ocfs2…プロパティ変更 mounted.ocfs2…OCFS2を表示 o2info…FS情報 o2image…metaコピー復元 O2CBコンポーネント…/etc/sysconfig/o2cb o2nm…ノードマネージャ o2hb…heartbeat o2net…ネットワーク o2dlm…ロック dlmfs…インメモリFS
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

最難関と名高いLPIC202のチートシート

dns rndc dumpdb…デフォルトのファイルにダンプ ※引数不可 rndc reload…ゾーン再読み込み、引数可 Apacheサーバ SSLCertificateFile…中間CA SSLCertificateKeyFile…秘密鍵 SSLCACertificateFile…クライアント認証CA証明書 SSLCACertificatePath…クライアント認証CA証明書のDir MaxClients…クライアント数 Satisfy Any…allowとrequireどっちかで認証 Satisfy All…allowとrequireどっちもで認証 sambaサーバ nmblookup -M…マスターブラウザ pdbedit -L…Samba一覧 testparm…smb.conf構文check samba-tool…AD管理DNS管理 net ads join…ADに参加 write list…書込許可user username map…WinユーザをSambaに hide dot files….始動file非表示 workgroup…AD,NetBIOS指定 guest ok…guestアクセス許可 public…guestアクセス許可 server string...サーバ説明文 username map…linuxユーザをwindowsクライアントで共有する為のファイル指定 winbind…winユーザをsambaで使う、PAMを使う場合モジュール必要、 NSSを使う場合/etc/nsswitch.confの編集が必要 security=share →userなしpassだけでログイン  失敗したらゲスト unix password sync…linux,sambaパス同期 null passwords…空パス encrypt passwords…暗号化パス LDAP LDIF…エントリは空行、属性は:(Base64の場合は::)で区切る LDIF設定ファイルは/slapd.d/配下に置かれる olcSuffix、olcRootdnはシステムによって使い分ける openLDAPサーバ slapcat…DBからLDIF出力 slaptest…構文チェック slapindex…index作成 olcLogLevel…syslogに出力するログレベル olcInclude…includeファイル指定 olcObjectClasses…slapd-configオブジェクトクラス rootpw…DB管理者のパス argsfile…コマンド引数を格納 filter…検索フィルタにマッチ changetype…LDIF追加削除 suffix…ディレクトリトップのDNを指定 logfile…デバッグログの出力先 rootdn…DB管理者のDN idletimeout…アイドル状態のクライアント接続を強制的に切断 changetype… エントリの追加、削除 メールサーバ postconf…設定確認 -n デフォルトから変更値 postfix check…構文チェック ・master.cf smtps…TLS設定 ・main.cf smtpd_tls_key_file…秘密鍵 smtpd_tls_cert_file…サーバ証明書 smtpd_tls_CAfile…CA証明書 smtpd_use_tls…2.2でTLS有効化 smtpd_enforce_tls…TLS強制 inet_interfaces…IF名 home_mailbox…ホームディレクトリ配下 mailbox_command…ローカル配送プログラム mail_spool_directory…メールスプールディレクトリ mydestination…ローカル配送を行うドメイン mynetworks…リレー許可クライアント mydomain…ドメイン myorigin…@以降ドメイン名 myhostname…ホスト名 nginx server…基本設定、待ちポート proxy_pass…httpからのURLを記載 proxy_set_header…串ヘッダー追加、再定義 fastcgi_pass…FastCGIサーバ root…最上位 server_name…VM名 location…リクエストURI PAM pam_deny.so…全て拒否 pam_securetty.so…/etc/securettyのみ通す pam_env.so…環境変数 pam_wheel.so…wheelグループ pam_ldap.so…ldap pam_sss.so…sssd pam_nologin.so…存在したらrootのみ pam_cracklib.so…書式制限 pam_limits.so…制御 pam_listfile.so…任意ファイル session…ログ記録 password…パス account…アカ auth…ユーザ認証 required…成功必須。失敗しても続行 requisite…成功必須。失敗したら続行しない sufficient…requiredが全成功なら成功。失敗なら次のモジュールへ session…ユーザのログインを記録 other…設定ファイルがない場合参照される DHCP オプションでサービスできるもの → IP,サブネット,nis,dns IPv6の場合はsubnet6、range6を指定 dhcpd.leases…貸出情報 radvd.conf…ルータ広告 hardware…mac ※設定項目はoptionをつける サーバー系はsをつける iptables -D…ルール削除 -P…チェインにターゲット -N…新チェイン -X…チェイン削除 iptables-restore…復元 iptables-save…保存 sieve fileinto…mailboxに配送 keep…補完 allof…論理積 anyof…論理和 require…拡張機能コマンド procmail…MTAから配信 dovecot mechanisms…認証方式 ssl_cert…証明書 ssl_key…秘密鍵 mail_location…格納方法場所 SSL…tls Courier-IMAP…Mairdirのみサポート doveadm…reload,stop,mailbox(管理),who(一覧) sieve…アーキテクチャに依存しない、配信時作動 verbose_proctitle…ps axでユーザ名IP表示 mail_location…格納形式、格納先 imaps 993 pop3s 995 NFS ユーザID、グループIDはクライアントと統一する sync…書き込み後に応答 async…書き込み前に応答 exportfs…nfsクライアントに対して nfsstat…rpc,nfsの統計 ネットワーク DNAT --to-destination [IP]…別サーバに転送 GUA…2000::/3,グローバルIP6,GW, LLA…fe80::/64,ローカルIP6,サブネットが指定出来ないのでルーティング不可(作成時のみGW可) ULA…ユニキャストIP6,アドレス重複回避,GW vsftpd anonymous_enable=YES…anonymous FTPとして利用(デフォルト) anon_root…anonymous FTP rootディレクトリ(デフォルトは/var/ftp) SSH /etc/sshd/sshd_config SSH…設定ファイルのPORTで1024以上のポートを指定 ~/.shosts…SSHのパスログイン省略 PermitRootLogin…直接rootログイン(noでセキュリティ強化) PubkeyAuthentication…公開鍵認証(YESでセキュリティ強化) IgnoreRhosts…YESで ~/.rhosts、~/.shosts を無視(YESでセキュリティ強化) X11Forwarding…YESでX11のポートフォワーディングを許可 OpenVPN ・サーバの秘密鍵ファイル名とサーバのポート番号を記録 ・ポートは1194 ・port [番号] でポート番号を指定できる ・ポート番号を動的に割り当てるのは「nobind」(bindで固定) client-to-client…クライアント間の通信ができるように ※サーバに設定 重要度 DNS S 3 DNS Z 3 DNS保護 2 Web S 4 HTTPS 3 proxy 2 nginx 2 samba 5 NFS 3 DHCP 2 PAM 3 LDAP 2 O LDAP 4 mail 4 mail n 2 meir r 2 route 3 FTP 2 SHH 4 sectool 3 openvpn 2 計60問
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LPIC201かいつまんだチートシート

htop Cpuコア、メモリ、swapの使用率 iostat システムCPU、Disk IO カーネルイメージ /boot/vmlinuz-2.6.3 初期RAMディスクイメージ /boot/initrd.img-2.6.3 カーネルアドレスマップ /boot/System.map-2.6.3 カーネルコンフィギュ /boot/config-2.6.3 カーネルに必要なファイル /usr/src/linux/ カーネル各種設定 /usr/src/linux/.config カーネル本体 /usr/src/linux/kernel/ カーネルのビルド時に参照する資料 /usr/src/linux/Documentation/ makeやカーネルのver情報 /usr/src/linux/Makefile make modules_installインストール後 /lib/modules/2.6.3/ カーネルパラメータを恒久的に変更dir /etc/sysctl.d/ Red Hatのcrondの自動起動調べる chkconfig --list crond カーネルイメージにルートファイル位置を書き込み rdev xfs情報 xfs_info 作成済XFSに対して様々な設定 xfs_setup mke2fs実際には実行しない -n ext2/ext3/ext4ファイルシステムのチェック e2fsck 作成済extに対して設定 tune2fs ブロックデバイス全体の暗号化 dm-crypt ext対話的デバッグ debugfs レイドの情報を表示 -Q --query レイドの詳細情報 -D --detail RAID を構築 0xfd RAID管理・操作 /etc/mdadm.conf /etc/mdadm/mdadm.conf RAID アレイの状態 /proc/mdstat iscsiadm接続先 -p --portal SCSIターゲットを指定 -T --targetname SSD最適化 fstrim iSCSIターゲットを一意に識別 IQN 共有ライブラリの検索パス LD_LIBRARY_PATH
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LPIC102個人的なチートシート

lpic 102 個人的なチートシート 自分用に環境変数を設定 ~/.bash_profile 特殊変数、実行したシェルスクリプト名 $0 現在のシェルのプロセス番号 $$ 許可リストへ追加 xhost +172.16.0.4 環境変数によるXサーバの指定 export DISPLAY=172.16.0.1:0 X Window Systemのエラー .xsession-errors MonitorセクションとDeviceセクションの組み合わせ Screen 「XDM」の設定ファイル /etc/X11/xdm/xdm-config ランレベル3からX Window Systemを起動 startx xinit ~/.xinitrc /etc/X11/xinit/xinitrc グラフィカルログイン使用プロトコル XDMCP useraddデフォルトの値 /etc/default/useradd user1を削除ホームディレクトリも一緒に削除 userdel -r user1 グループアカウント「GA」のグループ名を「GB」へ変更 groupmod -n GB GA 一般ユーザのログインを禁止したい場合 /etc/nologin パスワード無効化 ! * グループのパスワードやメンバーを設定 gpasswd 一時的なtimerユニット作成 systemd-run ユーザーのcron設定ファイル /var/spool/cron/ systemdにおいてtimerユニットを表示 systemctl list-timers 1回限りのジョブを削除 at -d atrm /etc/crontabスクリプトファイルを置くDir /etc/cron.d/ 1回限りのジョブの一覧 atq at -l ロケール 通貨:LC_MONETARY 数値書式:LC_NUMERIC 文字分類:LC_CTYPE 日付時刻:LC_TIME 言語:LC_MESSAGES アドレス:LC_ADDRESS 名前:LC_NAME 環境変数を設定してAsia/Tokyoを使用 export TZ=Asia/Tokyo /etc/timezoneで使用できるタイムゾーンの値を表示 tzselect ロケール設定ファイル /etc/locale.conf タイムゾーンの情報ががあるDir /usr/share/zoneinfo/ システム時刻や時刻同期の状態を表示 timedatectl TZ設定:set-timezone TZ表示:list-timezones ntp同期:set-ntp 時刻設定(HWとSY):set-time HW→SYS反映 hwclock --hctosys SYS→HW反映 hwclock --systohc HWkクロック時刻を表示 hwclock -r chronyc ズレ具合:difile 時刻ソース:sources ログローテーションの設定 /etc/logrotate.conf ジャーナルファイルに書き込む systemd-cat journalctl 最新:-r、--reverse Dir:-D、--directory 古い削除:--vacuum-time 表示可能:-l、--full サイズ削除:--vacuum-size 行表示:-n、--lines ローテーション機能 logrotate ホスト名やネットワークを設定 /etc/sysconfig/network レガシーで印刷ジョブを削除 lprm
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ultra96/Ultra96-V2 向け Ubuntu20.04で Lima を動かしてみた(ストライド問題編)

はじめに Lima とは Mali-400/450 用のオープンソースなグラフィックドライバです。筆者は Lima を Ultra96/Ultra96-V2 向け Ubuntu 20.04 で試験的に動かしてみました。動かすのに少々苦労したので、その方法を何回かに分けて説明します。 概要編 DRM Lima 編 DRI Lima 編 共有バッファ編 ストライド問題編(この記事) インストール編(近日公開予定) Ubuntu Desktop ビルド編(近日公開予定) 共有バッファ編で説明したバッファの共有に際して、バッファオブジェクトのストライドの不一致によるバッファ共有が失敗する問題が起こりました。この記事ではその問題の原因とその対応について説明します。 なお、現時点(2021年4月)では、Ubuntu 20.04 の gnome-shell が動作するところまで確認していますが、すべてのアプリケーションで動作を確認したわけでは無いことに注意してください。 ストライド問題 ストライドとは 2次元画像を格納するためのバッファを確保する際、画像の横幅の画素数 width 、画像の高さ(=行数) height、1画素あたりのビット数 bpp(BitPerPixel) に基づいてバッファの容量を計算します。しかし、これだけの情報だけでバッファを確保した場合、ハードウェアによっては遅くなったりそもそも動かなかったりすることがあります。 何故ならハードウェアにとって有利な画素単位 bpp や 画像の横幅 width が存在するからです。例えば、64bit CPU の場合は画像の先頭アドレスや横幅のバイト数が 8Byte(64bit) 単位でアライメントされていたほうが有利になります。あるいは、データキャッシュも考慮した場合は、データキャッシュのラインサイズ(例えば64バイト)単位でアライメントするとさらなる高速化が期待できます。 画像を格納するバッファを用意する際、画像の横幅のバイト数を、画像の横幅の画素数 width ×1画素あたりのビット数 bpp / 8Byte ではなく、ハードウェアに有利なバイト数にした方がよいことがあります。このハードウェアに有利な横幅のバイト数のことをストライドと言います。 DRI Lima のストライド Lima はARMのMali-400/450組み込みGPUをサポートするオープンソースのグラフィックスドライバーです。Mali-400/450 は組み込み GPU なので、扱える画像サイズに次のような制限があります。 画像の横幅 width は16 pixel 単位でアライメントされている 画像の高さ height は 16 line 単位でアライメントされている 画像の bpp は 8ビット、16ビット、32ビットの3種類 画像バッファの開始アドレスは64バイトにアライメントされている つまり、DRI Lima が想定するストライドは画像の横幅 width を16 pixel 単位で切り上げた画素数×(1Byte(=8bit) or 2Byte(=16bit) or 4Byte(=32bit)) になります。 DRM Xlnx のストライド DRM Xlnx の GEM バッファオブジェクトを生成する部分は次のようになっています。 drivers/gpu/drm/xlnx/xlnx_gem.c.c /* * xlnx_gem_cma_dumb_create - (struct drm_driver)->dumb_create callback * @file_priv: drm_file object * @drm: DRM object * @args: info for dumb scanout buffer creation * * This function is for dumb_create callback of drm_driver struct. Simply * it wraps around drm_gem_cma_dumb_create() and sets the pitch value * by retrieving the value from the device. * * Return: The return value from drm_gem_cma_dumb_create() */ int xlnx_gem_cma_dumb_create(struct drm_file *file_priv, struct drm_device *drm, struct drm_mode_create_dumb *args) { int pitch = DIV_ROUND_UP(args->width * args->bpp, 8); unsigned int align = xlnx_get_align(drm); if (!args->pitch || !IS_ALIGNED(args->pitch, align)) args->pitch = ALIGN(pitch, align); return drm_gem_cma_dumb_create_internal(file_priv, drm, args); } ここで重要なのが、xlnx_get_align() です。ストライド(この関数内では pitch という名称) は、この関数の戻り値が示すバイト単位でアライメントされます。ZynqMP の場合、xlnx_get_align() の戻り値は256バイトです。と言うのもZynqMP の場合、DRM Xlnx はディスプレイポートコントローラーを制御しています。ディスプレイコントローラーのDMA にはストライド256バイト単位にアライメントされていなければならないようです。このストライドの制限の説明は『Zynq UltraScale+ MPSoC Technical Reference Manual UG1085(v1.0)』の「Chapter 31 DisplayPort Controller」 の「DisplayPort DMA」にあります。 STRIDE Field A 14-bit field indicates the stride value in a 16-byte resolution. This field is only used in contiguous mode when the transfer size is larger than the line size. It is not used in fragmented mode, as it is always line wide. The stride value must be 256-byte aligned. ストライドの不一致 ZynqMP で X Serverの DRI3拡張機能を使う場合、DRM Xlnx が提供する バッファオブジェクトを DRI Lima が直接アクセスします。その際、DRI Lima が想定しているストライドと DRM Xlnx が提供しているバッファオブジェクトのストライドが一致していないと、次のようなエラーが発生してgnome-shell が異常終了しました。 /var/log/syslog Apr 30 02:24:23 ubuntu-fpga gnome-shell[953]: error: import buffer not properly aligned このエラーメッセージを出しているのは DRI Lima の lima_resource_from_handle() です。インポートしたバッファオブジェクトのストライドとサイズをチェックして、条件を満たさなかった場合はエラーを返しています。 mesa-20.2.6/src/gallium/drivers/lima/lima_resource.c static struct pipe_resource * lima_resource_from_handle(struct pipe_screen *pscreen, const struct pipe_resource *templat, struct winsys_handle *handle, unsigned usage) { : (中略) : /* check alignment for the buffer */ if (res->tiled || (pres->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL))) { unsigned width, height, stride, size; width = align(pres->width0, 16); height = align(pres->height0, 16); stride = util_format_get_stride(pres->format, width); size = util_format_get_2d_size(pres->format, stride, height); if (res->levels[0].stride != stride || res->bo->size < size) { debug_error("import buffer not properly aligned\\n"); goto err_out; } res->levels[0].width = width; } else res->levels[0].width = pres->width0; return pres; err_out: lima_resource_destroy(pscreen, pres); return NULL; } 解決方法 このストライド問題を解決するためには、DRM Xlnx と DDX Xlnx の双方を修正する必要がありました。 DRM Xlnx の修正 DRM Xlnx の GEM バッファオブジェクトを生成する際、カーネルパラメータ gem_alignment_size を使ってアライメントするバイト数を指定するようにします。gem_alignment_size が0以外の時は、その値でアライメントします。また、gem_alignment_size が0の時はxlnx_get_align() の戻り値でアライメントします。なお、互換性のため、xlnx_get_align() の戻り値でアライメントするためにgem_alignment_size の初期値は0にしています。lima を使う場合は gem_alignment_size に8 を指定します。 drivers/gpu/drm/xlnx/xlnx_gem.c /* * gem_alignment_size module parameter */ static int gem_alignment_size = 0; module_param( gem_alignment_size , int, S_IRUGO); MODULE_PARM_DESC( gem_alignment_size , "xlnx gem alignment size"); int xlnx_gem_cma_dumb_create(struct drm_file *file_priv, struct drm_device *drm, struct drm_mode_create_dumb *args) { unsigned int align; if (gem_alignment_size == 0) align = xlnx_get_align(drm); else align = gem_alignment_size; if (!args->pitch || !IS_ALIGNED(args->pitch, align)) args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), align); DRM_DEBUG("width=%d, height=%d, bpp=%d, pitch=%d, align=%d\\n", args->width, args->height, args->bpp, args->pitch, align); return drm_gem_cma_dumb_create_internal(file_priv, drm, args); } DDX Xlnx の修正 Lima を使う場合、DRM Xlnx の gem_alignment_size に8 を指定する必要があります。そのため、ディスプレイポートコントローラーに出力するためのバッファオブジェクトでストライドのアライメントが256バイト単位にならないことがあります。このままではディスプレイに出力できません。 そこで DDX Xlnx の create_custom_gem() で、ディスプレイ出力用のバッファの場合(create_gem->buf_type == ARMSOC_BO_SCANOUT)はストライドを256バイト単位でアライメントし、それ以外の用途のバッファの場合は幅と高さを Lima の仕様にあわせてアライメントするように修正します。 src/drmmode_xilinx/drmmode_xilinx.c #define DIV_ROUND_UP(val,d) (((val) + (d ) - 1) / (d)) #define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1)) static int create_custom_gem(int fd, struct armsoc_create_gem *create_gem) { struct drm_mode_create_dumb arg; int ret; memset(&arg, 0, sizeof(arg)); if (create_gem->buf_type == ARMSOC_BO_SCANOUT) { arg.height = create_gem->height; arg.width = create_gem->width; arg.bpp = create_gem->bpp; /* For Xilinx DPDMA needs pitch 256 bytes alignment */ arg.pitch = ALIGN(create_gem->width * DIV_ROUND_UP(create_gem->bpp,8), 256); } else { /* For Lima need height and width 16 bytes alignment */ arg.height = ALIGN(create_gem->height, 16); arg.width = ALIGN(create_gem->width , 16); arg.bpp = create_gem->bpp; arg.pitch = arg.width * DIV_ROUND_UP(create_gem->bpp,8); } ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg); if (ret) return ret; create_gem->handle = arg.handle; create_gem->pitch = arg.pitch; create_gem->size = arg.size; return 0; } 参考 Lima web (https://gitlab.freedesktop.org/lima/web) Mesa 3D and Direct Rendering Infrastructure wiki (https://dri.freedesktop.org/wiki) https://github.com/ikwzm/ZynqMP-FPGA-Ubuntu20.04-Lima-Ultra96 https://github.com/ikwzm/xf86-video-armsoc-xilinx 『Zynq UltraScale+ MPSoC Technical Reference Manual UG1085(v1.0)』
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

大いなる力には大いなる責任が伴う〜sudoの設定を求めて〜

あなたは以下のような文言を見たことがありますか? あなたはシステム管理者から通常の講習を受けたはずです。 これは通常、以下の3点に要約されます: #1) 他人のプライバシーを尊重すること。 #2) タイプする前に考えること。 #3) 大いなる力には大いなる責任が伴うこと。 これはsudoコマンドを打った時にたまに出てくる警告文です。 この記事を書こうと思ったきっかけはこのツイートを見たことです。 とあるシステムで特権ユーザーにスイッチする時に「大いなる力には大いなる責任が伴う」ってメッセージが出てくるんやけど、めっちゃすこ。彡(^)(^)— gonsuke777 (@ora_gonsuke777) April 26, 2021 わかる。 自分は初めてみた時はドキッとしました。 「sudo使おうとしてごめんなさい・・・。でも仕方ないよね?」 と改めて確認したので効果ありました。笑 「大いなる力には大いなる責任が伴う」 この元ネタはスパイダーマンのセリフらしいです。 本質をついた良い言葉ですよね。 sudoの「大いなる力」の元ネタを探して - Qiita でもシステムによって見かける時と見かけない時があるよな〜。 そういう設定があるのかも? ・・・自分のPCでも表示させてみたい! そう思ってsudoの設定を探す旅に出かけました。 編集 調べてみると、sudoの設定は /etc/sudoers に格納されている模様。 しかもそのフォルダを安全に編集するために visudo というコマンドがあるらしいです。 使い方はviとほぼ同じですが、sudo設定のエラーチェックをしてくれます。 sudoの権限を設定するvisudoコマンド【Linuxコマンド集】 $ sudo visudo これだけで編集画面へいけます。 設定 Man page of SUDOERS sudoersの設定方法です。 関係ある部分を引用させてもらいます。 lecture sudo はパスワードプロンプトに添えて簡単な訓戒を表示することができる。 このオプションはその訓戒をいつ表示するかを決定する。以下の値が可能である。 always いつでも必ず訓戒を表示する。 never 訓戒をまったく表示しない。 once ユーザがはじめて sudo を実行したときだけ表示する。 値を指定しないと、once を指定したことになる。頭に '!' を付けて、 このオプションを否定すると、値に never が使用される。 デフォルトの値は once である。 lecture_file 標準の訓戒とは別の sudo の訓戒を書き込んだファイルのパス。 指名したファイルが存在すれば、sudo は標準の訓戒の代わりに、それを使用する。 デフォルトでは、プログラムに埋め込まれた訓戒が使用される。 なるほど。 実践 表示させてみる とりあえず設定に lecture = "always" を追加してみよう! それからデフォルトのものを表示させたいので、lecture_fileの行をコメントアウト。 /etc/sudoers ## # Override built-in defaults ## ... Defaults lecture = "always" #追加 #Defaults lecture_file = "/etc/sudo_lecture" #コメントアウト ちなみに設定がalwaysといってもターミナル開いてる間は警告表示が無効な様子。 警告の表示を再度出したい場合は一旦ターミナルを終了するといいみたいです。 ターミナルを再起動して、sudoを実行。 $ sudo ls We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things: #1) Respect the privacy of others. #2) Think before you type. #3) With great power comes great responsibility. Password: これだ! ・・・日本語訳にしたいな。 日本語で表示させる 言語環境設定のlanguagesetupとか設定してもなにも変化なし。 localeコマンドで環境言語を見てみても日本語設定になってるので問題なさそう。 となると別にプログラムに組み込まれてるわけではないのかな。 じゃあもう表示する文言を自分で用意しちゃおう。 警告文表示ファイル作成する。 $ sudo vim /etc/sudo_lecture_japanese /etc/sudo_lecture_japanese あなたはシステム管理者から通常の講習を受けたはずです。 これは通常、以下の3点に要約されます: #1) 他人のプライバシーを尊重すること。 #2) タイプする前に考えること。 #3) 大いなる力には大いなる責任が伴うこと。 保存。 作成したファイルを指定する。 $ sudo visudo /etc/sudoers Defaults lecture = "always" Defaults lecture_file = "/etc/sudo_lecture_japanese" そして今度こそ!!! $ sudo ls あなたはシステム管理者から通常の講習を受けたはずです。 これは通常、以下の3点に要約されます: #1) 他人のプライバシーを尊重すること。 #2) タイプする前に考えること。 #3) 大いなる力には大いなる責任が伴うこと。 できた!!! これでsudoするたび警告が表示されます。 やったね! おしまい。 その他参考 sudoで覚えておくと便利な設定・使い方 | 俺的備忘録 〜なんかいろいろ〜
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ultra96/Ultra96-V2 向け Ubuntu20.04で Lima を動かしてみた(共有バッファ編)

はじめに Lima とは Mali-400/450 用のオープンソースなグラフィックドライバです。筆者は Lima を Ultra96/Ultra96-V2 向け Ubuntu 20.04 で試験的に動かしてみました。動かすのに少々苦労したので、その方法を何回かに分けて説明します。 概要編 DRM Lima 編 DRI Lima 編 共有バッファ編(この記事) ストライド問題編 インストール編(近日公開予定) Ubuntu Desktop ビルド編(近日公開予定) この記事では、DRI コンポーネント間でバッファを共有する仕組みである DRI2 と DRI3 について説明し、Lima を動かすために DDX Lima(Xorg Device Dependent X Driver for Lima) を DRI3 に対応した点を説明します。 なお、現時点(2021年4月)では、Ubuntu 20.04 の gnome-shell が動作するところまで確認していますが、すべてのアプリケーションで動作を確認したわけでは無いことに注意してください。 共有バッファの仕組み GEM について DRI(Direct Rendering Infrastructure) は単一のソフトウェアではなく、いくつもの DRI コンポーネントで構成されています。これらの DRI コンポーネント間で画像データをやりとりするための手段として、共有バッファが用いられます。しかもディスプレイドライバやレンダリングエンジンのようなハードウェアでも使うため、DRM(irect Rendering Manager - Linux カーネル部分の DRI コンポーネント) でも使える共有バッファが必要です。 GEM(Graphics Excution Manager) は DRM の一部であり、複数のアプリケーションの間でバッファを共有するための API を提供しています。 Fig.1 GEM(Graphics Excution Manager) DRI2 について DRI2 は複数のアプリケーションの間でバッファを共有するための X Server の拡張機能です。DRI2 では、バッファの割り当ては X Server 自体によって行われ、DRI クライアントは DRI2 拡張機能で使用可能な DRI2GetBuffers などの操作を呼び出すことにより、これらのバッファを取得してウィンドウへのレンダリングを行います。内部的には、DRM 内の GEM が Linux カーネル内にバッファの実体を保持し、GEM 名(DRM にアクセスする複数のプロセスが同じバッファを参照できるようにするために GEM API によって提供されるグローバルハンドルの一種) を介して DRI クライアントにバッファの参照を渡します。DRI クライアントは渡された GEM 名を DRM に渡すことでバッファへのアクセス(open/mmap/closeなど)を行います。 残念ながら、DRI2 では Lima を動作させることが出来ませんでした。これはあくまでも筆者の推測ですが、どうやら DRI2 は、単一の DRM が提供するバッファを複数の DRI コンポーネントで共有することを想定しているようで、Lima のように 3D レンダリング専用の DRM とディスプレイ用の DRM にわかれているような、複数の DRM の間でバッファを共有することを想定していないようです(要検証)。 その結果、DRI2 の場合、Ubuntu20.04 の gnome-shell を動かそうとすると、libGL 内の DRI Lima Driver が X Server から渡された GEM 名でのバッファのオープンに失敗して、動きませんでした。 DRI3 について DRI3 は DRI2 で生じたいくつかの問題を修正するために 2013年に開発されました。DRI3 は DRI2 と比較して次の点が異なります。 DRI3 クライアントは、バッファの割り当てを X Server に依存するのではなく、自分自身が行います。 DRI3 は、 DRI2 が採用していた(古く安全で無い)GEM 名に基づくバッファオブジェクトの受け渡しをやめて、(安全で用途の広い)ファイル拡張子を使ったPRIME DMA-BUFs というバッファオブジェクトの受け渡しを採用しています。 ここで言う DMA-BUF というのは Linux カーネル内部の DMA バッファの共有 API の略称のことです。これは、異なる種類のデバイスドライバが管理している複数のデバイス間で DMA バッファを共有するための一般的なメカニズムを提供します。 DMA-BUF の特に重要な点は、異なるデバイスドライバ間で DMA バッファを共有できることです。DRI3 は この DMA-BUF という DMA バッファ共有 API を使うことによって、複数の DRM 間でバッファオブジェクトの共有を可能にしています。 バッファオブジェクトの受け渡しには DMA-BUF が提供するファイル記述子が使われます。 この DMA-BUF という機能は DRM Core にすでに実装されています。また、DRI Lima は DRI3 に対応しています。そして X Server が DRI3 拡張に対応するためには DDX(Device Dependent X)ドライバが DRI3 に対応している必要がありますが、残念ながら xlnx が提供している DDX ドライバは DRI3 は対応していません。 DDX Xlnx を DRI3 対応にする Lima を動かすためには DRI2 ではダメで DRI3 が必要なようです。しかし、X Server が DRI3 拡張に対応するためには DDXドライバが DRI3 に対応している必要がありますが、残念ながら xlnx が提供している DDX ドライバは DRI3 は対応していませんでした。この章では DDX Xlnx を DRI3 に対応するための変更点を説明します。 リポジトリ この章で説明する内容は以下の github リポジトリに用意しています。 https://github.com/ikwzm/xf86-video-armsoc-xilinx https://github.com/ikwzm/xf86-video-armsoc-xilinx/tree/master https://github.com/ikwzm/xf86-video-armsoc-xilinx/tree/xilinx-dri3-develop 2021年4月現在、まだ開発中のため DRI3 に対応したソースコードは xilinx-dri3-develop ブランチにあります。master ブランチにはまだ反映されていないことに注意してください。master ブランチには修正前のソースコードがあります。 armsoc_dri3.c DRI3 に対応するために armsoc_dri3.c を新しく作ります。armsoc_dri3.c には次の関数および変数を定義します。 ARMSOCDRI3ScreenInit() armsoc_sync_init() armsoc_dri3_open() armsoc_dri3_pixmap_from_fd() armsoc_dri3_fd_from_pixmap()  ARMSOCDRI3ScreenInit DDX ドライバを DRI3 に対応するためには、初期化時に次の関数を用意して dri3_scrren_init() を呼び出す必要があります。 open() - DRM をオープンする関数 pixmap_from_fd - ファイル記述子で示されたバッファオブジェクトから Pixmap を作る関数 fd_from_pixmap - Pixmap からバッファオブジェクトのファイル記述子を得る関数 また、初期化時にバッファ共有のために miSyncShmScreenInit() を呼び出す必要があります。そこで次のような ARMSOCDRI3ScreenInit() を定義します。 src/armsoc_dri3.c static dri3_screen_info_rec armsoc_dri3_screen_info = { .version = DRI3_SCREEN_INFO_VERSION , .open = armsoc_dri3_open , .pixmap_from_fd = armsoc_dri3_pixmap_from_fd, .fd_from_pixmap = armsoc_dri3_fd_from_pixmap, }; Bool ARMSOCDRI3ScreenInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); if (!armsoc_sync_init(pScreen)) return FALSE; if (!dri3_screen_init(pScreen, &armsoc_dri3_screen_info)) { WARNING_MSG("dri3_screen_init failed\\n"); return FALSE; } return TRUE; }  armsoc_sync_init armsoc_sync_init() は 前節のARMSOCDRI3ScreenInit() から呼び出され、miSyncShmScreenInit() を呼び出します。 src/armsoc_dri3.c static Bool armsoc_sync_init(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); if (!xf86LoaderCheckSymbol("miSyncShmScreenInit")) { WARNING_MSG("SYNC extension fences disabled because " "miSyncShmScreenInit symbol unresolved\\n"); return FALSE; } if (!miSyncShmScreenInit(pScreen)) { WARNING_MSG("miSyncShmScreenInit failed\\n"); return FALSE; } return TRUE; }  armsoc_dri3_open armsoc_dri3_open() は DRM ドライバをオープンして認証を行います。 src/armsoc_dri3.c static int armsoc_dri3_open(ScreenPtr pScreen, RRProviderPtr provider, int* out) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct ARMSOCRec* pARMSOC = ARMSOCPTR(pScrn); int fd; drm_magic_t magic; if (!pARMSOC->deviceName) { DEBUG_MSG("pARMSOC->deviceName failed"); goto badalloc; } fd = open(pARMSOC->deviceName, O_RDWR | O_CLOEXEC); if (fd < 0) { DEBUG_MSG("open(%s) failed", pARMSOC->deviceName); goto badalloc; } if (drmGetMagic(fd, &magic) < 0) { if (errno == EACCES) { goto success; } else { DEBUG_MSG("drmGetMagic(%s) failed", pARMSOC->deviceName); goto badmatch; } } DEBUG_MSG("drmGetMagic(%s) magic=%d", pARMSOC->deviceName, magic); if (drmAuthMagic(pARMSOC->drmFD, magic) < 0) { DEBUG_MSG("drmAuthMagic(%d,%d) failed", pARMSOC->drmFD, magic); goto badmatch; } success: *out = fd; DEBUG_MSG("DRI3 Open success"); return Success; badmatch: close(fd); ERROR_MSG("DRI3 Open failed error=BadMatch"); return BadMatch; badalloc: ERROR_MSG("DRI3 Open failed error=BadAlloc"); return BadAlloc; }  armsoc_dri3_pixmap_from_fd armsoc_dri3_pixmap_from_fd() は他の DRM が管理しているバッファオブジェクト(を示す DMA-BUF API が生成したファイル記述子)から Pixmap を作る関数です。 src/armsoc_dri3.c static PixmapPtr armsoc_dri3_pixmap_from_fd(ScreenPtr pScreen, int fd , CARD16 width , CARD16 height , CARD16 stride , CARD8 depth , CARD8 bpp ) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct ARMSOCRec* pARMSOC = ARMSOCPTR(pScrn); PixmapPtr pixmap = NULL; struct ARMSOCPixmapPrivRec* priv; depth と bpp(bit per pixel) の値をチェックします。DDX Xlnx では depth は8以上、bppは 8、16、32 のみサポートしています。 src/armsoc_dri3.c if (depth < 8) { DEBUG_MSG("(fd=%d,width=%d,height=%d,stride=%d,depth=%d,bpp=%d) depth < 8 failed", fd, width, height, stride, depth, bpp); goto failed; } switch (bpp) { case 8: case 16: case 32: break; default: DEBUG_MSG("(fd=%d,width=%d,height=%d,stride=%d,depth=%d,bpp=%d) bpp failed", fd, width, height, stride, depth, bpp); goto failed; } まずは Pixmap を生成します。その際、user_hint に ARMSOC_CREATE_PIXMAP_IMPORT を指定します。Pixmap を生成するとき、通常は GEM にバッファを確保してそのバッファオブジェクトとPixmapと結びつけるのですが、user_hint にこの値をセットしているとバッファオブジェクトを生成しません。 その代わりに、armsoc_bo_import_with_dim() が生成したバッファオブジェクトを Pixmap に結びつけます。armsoc_bo_import_with_dim() は、他の DRM が管理しているバッファオブジェクト(を示す DMA-BUF API が生成したファイル記述子)をとりこんで、自身が管理するバッファオブジェクトを生成します。 src/armsoc_dri3.c pixmap = pScreen->CreatePixmap(pScreen, width, height, depth, ARMSOC_CREATE_PIXMAP_IMPORT); if (!pixmap) { DEBUG_MSG("(fd=%d,width=%d,height=%d,stride=%d,depth=%d,bpp=%d) CreatePixmap() failed", fd, width, height, stride, depth, bpp); goto failed; } priv = exaGetPixmapDriverPrivate(pixmap); if (!priv) { goto failed; } priv->bo = armsoc_bo_import_with_dim(pARMSOC->dev, fd, width, height, stride, depth, bpp); if (!priv->bo) { DEBUG_MSG("(fd=%d,width=%d,height=%d,stride=%d,depth=%d,bpp=%d) armsoc_bo_import_with_dim() failed", fd, width, height, stride, depth, bpp); goto failed; } Pixmap 生成時には設定できなかった stride を後付けで Pixmap に設定します。 src/armsoc_dri3.c if (!pScreen->ModifyPixmapHeader(pixmap, 0, 0, 0, 0, stride, NULL)) { DEBUG_MSG("(fd=%d,width=%d,height=%d,stride=%d,depth=%d,bpp=%d) ModifyPixmapHeader(pixmap=%p,stride=%d) failed", fd, width, height, stride, depth, bpp, pixmap, stride); goto failed; } 成功時には pixmap のアドレスを、失敗時には NULL を返します。 src/armsoc_dri3.c return pixmap; failed: if (pixmap) fbDestroyPixmap(pixmap); ERROR_MSG("DRI3 Pixmap from FD(%d) failed", fd); return NULL; }  armsoc_dri3_fd_from_pixmap armsoc_dri3_fd_from_pixmap() は、Pixmap が管理しているバッファオブジェクトを他の DRM と共有するためのファイル記述子を生成します。ファイル記述子とともに、バッファの横幅のバイト数を示す stride とバッファのバイト数を示す size も返します。 src/armsoc_dri3.c static int armsoc_dri3_fd_from_pixmap(ScreenPtr pScreen, PixmapPtr pixmap , CARD16* stride , CARD32* size ) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct armsoc_bo* bo; int fd; bo = ARMSOCPixmapBo(pixmap); if (!bo) { exaMoveInPixmap(pixmap); bo = ARMSOCPixmapBo(pixmap); if (!bo) { DEBUG_MSG("(pixmap=%p) bo==NULL failed", pixmap); goto failed; } } fd = armsoc_bo_export(bo); if (fd < 0) { DEBUG_MSG("(pixmap=%p) armsoc_bo_export(%p) failed", pixmap, bo); goto failed; } *stride = armsoc_bo_pitch(bo); *size = armsoc_bo_size(bo); DEBUG_MSG("(pixmap=%p,width=%d,height=%d,depth=%d,bpp=%d,*stride=%d,*size=%d) success Fd(%d)", pixmap, armsoc_bo_width(bo), armsoc_bo_height(bo), armsoc_bo_depth(bo), armsoc_bo_bpp(bo), *stride, *size, fd); return fd; failed: ERROR_MSG("DRI3 Fd From Pixmap(%p) failed", pixmap); return -1; } armsoc_dumb.c DRI3 に対応するために バッファオブジェクトを管理するソースコードのarmsoc_dumb.c に何点か修正が必要です。  struct armsoc_bo バッファオブジェクト管理のための構造体 struct armsoc_bo に、armsoc_dri3_pixmap_from_fd() で取り込まれたバッファオブジェクトかどうかを識別するためのメンバー変数 import を追加します。 src/armsoc_dumb.c @@ -62,6 +63,7 @@ struct armsoc_bo { uint32_t pitch; int refcnt; int dmabuf; + int import; /* initial size of backing memory. Used on resize to * check if the new size will fit */  armsoc_bo_new_with_dim armsoc_bo_new_with_dim() で自分自身でバッファオブジェクトを生成た場合は struct armsoc_bo のメンバー変数 import に0をセットします。 src/armsoc_dumb.c @@ -170,14 +172,77 @@ struct armsoc_bo *armsoc_bo_new_with_dim(struct armsoc_device *dev, new_buf->refcnt = 1; new_buf->dmabuf = -1; new_buf->name = 0; + new_buf->import = 0; return new_buf; }  armsoc_bo_import_with_dim armsoc_dri3_pixmap_from_fd() から呼び出されるarmsoc_bo_import_with_dim() を追加します。この関数は、他の DRM が管理しているバッファオブジェクト(を示す DMA-BUF API が生成したファイル記述子)をとりこんで、自身が管理するバッファオブジェクトを生成します。 まずは、DRM に対して DRM_IOCTL_PRIME_FD_TO_HANDLE を ioctl で呼び出し、ファイル記述子からバッファオブジェクトのハンドルを得ます。 src/armsoc_dumb.c +struct armsoc_bo *armsoc_bo_import_with_dim(struct armsoc_device *dev, int fd, + uint32_t width, uint32_t height, uint32_t stride, uint8_t depth, + uint8_t bpp) +{ +#ifdef DRM_IOCTL_PRIME_FD_TO_HANDLE + struct drm_prime_handle import_handle = { 0 }; + struct armsoc_bo *new_bo; + off_t seek; + int res; + + new_bo = malloc(sizeof(*new_bo)); + if (!new_bo) + return NULL; + + import_handle.fd = fd; + import_handle.flags = 0; + + res = drmIoctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &import_handle); + if (res) { + xf86DrvMsg(-1, X_ERROR, + " %s: DRM_IOCTL_PRIME_FD_TO_HANDLE({fd: %d}) failed. errno: %d - %s\\n", + __func__, import_handle.fd, errno, strerror(errno)); + free(new_bo); + return NULL; + } + DRM_IOCTL_PRIME_FD_TO_HANDLE で得たハンドル import_handle.handle を バッファオブジェクトのメンバー変数 handle にセットします。その他のバッファオブジェクトのメンバー変数を初期化します。また、 lseek() でバッファの最後のポインタを得ることでバッファオブジェクトの正味のサイズ original_size を得ます。 バッファオブジェクトの生成に成功した時は、そのポインタを返します。失敗した時は NULL を返します。 src/armsoc_dumb.c + new_bo->dev = dev; + new_bo->handle = import_handle.handle; + new_bo->size = stride * height; + new_bo->map_addr = NULL; + new_bo->fb_id = 0; + new_bo->pitch = stride; + new_bo->width = width; + new_bo->height = height; + new_bo->depth = depth; + new_bo->bpp = bpp; + new_bo->refcnt = 1; + new_bo->dmabuf = -1; + new_bo->name = 0; + new_bo->import = 1; + + seek = lseek(import_handle.fd, 0, SEEK_END); + if (seek < 0) { + xf86DrvMsg(-1, X_ERROR, + " %s: lseek({fd: %d}) failed. errno: %d - %s\\n", + __func__, import_handle.fd, errno, strerror(errno)); + armsoc_bo_unreference(new_bo); + return NULL; + } else if (new_bo->size > seek) { + xf86DrvMsg(-1, X_ERROR, + " %s: requerd size(%d) is lager than actual (%ld)\\n", + __func__, new_bo->size, (long)seek); + armsoc_bo_unreference(new_bo); + return NULL; + } else { + new_bo->original_size = seek; + return new_bo; + } +#else + return NULL; +#endif +} +  armsoc_bo_export バッファオブジェクトを他の DRM と共有するためのファイル記述子を生成する関数 armsoc_bo_export() を追加します。具体的にはDRM に対して DRM_IOCTL_PRIME_HANDLE_TO_FD を ioctl で呼び出して得たバッファオブジェクトを示すファイル記述子を返します。 src/armsoc_dumb.c +int armsoc_bo_export(struct armsoc_bo *bo) +{ + int res; + struct drm_prime_handle export_handle = { 0 }; + + export_handle.handle = bo->handle; + export_handle.flags = DRM_CLOEXEC; + + res = drmIoctl(bo->dev->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &export_handle); + if (res) { + xf86DrvMsg(-1, X_ERROR, + "DRM_IOCTL_PRIME_HANDLE_TO_FD(handle:0x%X) failed. errno: %d - %s\\n", + export_handle.handle, errno, strerror(errno)); + return -1; + } + xf86DrvMsg(-1, X_INFO, "DRM_IOCTL_PRIME_HANDLE_TO_FD(handle:0x%X) return: %d\\n", + export_handle.handle, export_handle.fd); + return export_handle.fd; +} +  armsoc_bo_imported バッファオブジェクトが armsoc_dri3_pixmap_from_fd() で取り込まれたかどうかを識別するための関数を追加します。 src/armsoc_dumb.c +int armsoc_bo_imported(struct armsoc_bo *bo) +{ + return bo->import; +} + armsoc_dumb.h バッファオブジェクト用のヘッダファイル armsoc_dumb.h に新しく追加した関数のarmsoc_bo_import_with_dim()、armsoc_bo_export()、armsoc_bo_imported() のプロトタイプを追加します。 src/armsoc_dumb.h @@ -74,6 +74,11 @@ struct armsoc_bo *armsoc_bo_new_with_dim(struct armsoc_device *dev, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, enum armsoc_buf_type buf_type); +struct armsoc_bo *armsoc_bo_import_with_dim(struct armsoc_device *dev, int fd, + uint32_t width, + uint32_t height, uint32_t stride, uint8_t depth, uint8_t bpp); +int armsoc_bo_export(struct armsoc_bo *bo); +int armsoc_bo_imported(struct armsoc_bo *bo); uint32_t armsoc_bo_width(struct armsoc_bo *bo); uint32_t armsoc_bo_height(struct armsoc_bo *bo); uint8_t armsoc_bo_depth(struct armsoc_bo *bo); armsoc_exa.h user_hint に設定するための定数 ARMSOC_CREATE_PIXMAP_IMPORT を追加します。 src/armsoc_exe.h @@ -108,7 +108,7 @@ struct ARMSOCPixmapPrivRec { #define ARMSOC_CREATE_PIXMAP_SCANOUT 0x80000000 - +#define ARMSOC_CREATE_PIXMAP_IMPORT 0x40000000 void *ARMSOCCreatePixmap2(ScreenPtr pScreen, int width, int height, int depth, int usage_hint, int bitsPerPixel, armsoc_exa.c Pixmap を生成する際に user_hint に ARMSOC_CREATE_PIXMAP_IMPORT が設定されたときの処理を追加します。  ARMSOCCreatePixmap2 ARMSOCCreatePixmap2() は X Server が Pixmap を生成する際に、DDX ドライバに対して呼び出される関数です。DDX Xlnx ではバッファオブジェクトを生成して Pixmap と関連づけます。 user_hint に ARMSOC_CREATE_PIXMAP_IMPORT が設定されたときは、バッファオブジェクトを生成しないように処理を追加します。 src/armsoc_exe.c @@ -88,10 +88,12 @@ ARMSOCCreatePixmap2(ScreenPtr pScreen, int width, int height, if (!priv) return NULL; - if (usage_hint & ARMSOC_CREATE_PIXMAP_SCANOUT) - buf_type = ARMSOC_BO_SCANOUT; + if (!(usage_hint & ARMSOC_CREATE_PIXMAP_IMPORT) && + (width > 0 && height > 0 && depth > 0 && bitsPerPixel > 0)) { + + if (usage_hint & ARMSOC_CREATE_PIXMAP_SCANOUT) + buf_type = ARMSOC_BO_SCANOUT; - if (width > 0 && height > 0 && depth > 0 && bitsPerPixel > 0) { /* Pixmap creates and takes a ref on its bo */ priv->bo = armsoc_bo_new_with_dim(pARMSOC->dev, width,  ARMSOCModifyPixmapHeader ARMSOCModifyPixmapHeader() は X Server が Pixmap の各種情報(Header) を書き換える場合に DDX ドライバに対して呼び出される関数です。 user_hint に ARMSOC_CREATE_PIXMAP_IMPORT が設定されたときは、バッファオブジェクトがまだ関連づけられていなかった時は何もせず正常終了する処理を追加しています。また、armsoc_dri3_pixmap_from_fd() で取り込まれたバッファオブジェクトの場合は画像の幅 width、高さ height、bitPerPixel は変更出来ないようにしています。 src/armsoc_exe.c @@ -225,10 +227,20 @@ ARMSOCModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, if (!pPixmap->drawable.width || !pPixmap->drawable.height) return TRUE; + if ((priv->usage_hint & ARMSOC_CREATE_PIXMAP_IMPORT) && !priv->bo) + return TRUE; + assert(priv->bo); if (armsoc_bo_width(priv->bo) != pPixmap->drawable.width || armsoc_bo_height(priv->bo) != pPixmap->drawable.height || armsoc_bo_bpp(priv->bo) != pPixmap->drawable.bitsPerPixel) { + if (armsoc_bo_imported(priv->bo)) { + ERROR_MSG("failed to resize %dx%d%d imported bo", + pPixmap->drawable.width, + pPixmap->drawable.height, + pPixmap->drawable.bitsPerPixel); + return FALSE; + } /* pixmap drops ref on its old bo */ armsoc_bo_unreference(priv->bo); /* pixmap creates new bo and takes ref on it */ armsoc_driver.h  struct ARMSOCRec DDX 全体を管理するための構造体 struct ARMSOCRec に DRI2と DRI3 を管理するためのメンバー変数を追加します。 src/armsoc_driver.h @@ -128,8 +128,22 @@ struct ARMSOCRec { */ struct ARMSOCEXARec *pARMSOCEXA; + /** record if success xf86LoadSubModule("dri2") */ + Bool dri2_available; + /** record if DRI >= 2 and success xf86LoadSubModule("dri2") */ + Bool dri2_enable; /** record if ARMSOCDRI2ScreenInit() was successful */ - Bool dri; + Bool dri2; + const char *dri2DriverName; + + /** record if success xf86LoadSubModule("dri3") */ + Bool dri3_available; + Bool dri3_override; + /** record if DRI >= 3 and success xf86LoadSubModule("dri3") */ + Bool dri3_enable; + + /** record if ARMSOCDRI3ScreenInit() was successful */ + Bool dri3; /** user-configurable option: */ Bool NoFlip;  ARMSOCDRI3ScreenInit ARMSOCDRI3ScreenInit() のプロトタイプ宣言を追加します。 src/armsoc_driver.h +/** + * DRI3 functions.. + */ +Bool ARMSOCDRI3ScreenInit(ScreenPtr pScreen); + armsoc_driver.c DDX ドライバの初期化時に、オプション "DRI" に3 が設定されていたと場合は ARMSOCDRI3ScreenInit() を呼び出すように変更します。  ARMSOCOptions xorg.conf 等で設定するオプション変数に "DRI" を追加します。 src/armsoc_driver.c @@ -102,6 +102,7 @@ _X_EXPORT DriverRec ARMSOC = { /** Supported options, as enum values. */ enum { OPTION_DEBUG, + OPTION_DRI_LEVEL, OPTION_NO_FLIP, OPTION_CARD_NUM, OPTION_BUSID, @@ -114,6 +115,7 @@ enum { /** Supported options. */ static const OptionInfoRec ARMSOCOptions[] = { { OPTION_DEBUG, "Debug", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_DRI_LEVEL, "DRI", OPTV_INTEGER, {0}, FALSE }, { OPTION_NO_FLIP, "NoFlip", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_CARD_NUM, "DRICard", OPTV_INTEGER, {0}, FALSE }, { OPTION_BUSID, "BusID", OPTV_STRING, {0}, FALSE },  ARMSOCPreInit オプション "DRI" の値に基づいてstruct ARMSOCRec の DRI2と DRI3 を管理するためのメンバー変数を設定します。 src/armsoc_driver.c @@ -771,6 +773,7 @@ ARMSOCPreInit(ScrnInfoPtr pScrn, int flags) rgb defaultMask = { 0, 0, 0 }; Gamma defaultGamma = { 0.0, 0.0, 0.0 }; int driNumBufs; + int driLevel; TRACE_ENTER(); @@ -932,12 +935,45 @@ ARMSOCPreInit(ScrnInfoPtr pScrn, int flags) } /* Load external sub-modules now: */ - if (!(xf86LoadSubModule(pScrn, "dri2") && - xf86LoadSubModule(pScrn, "exa") && - xf86LoadSubModule(pScrn, "fb"))) { + if (!(xf86LoadSubModule(pScrn, "exa") && + xf86LoadSubModule(pScrn, "fb"))) { goto fail2; } + /* Load dri2 and dri3 sub-modules */ + if (!xf86GetOptValInteger(pARMSOC->pOptionInfo, OPTION_DRI_LEVEL, &driLevel)) { + driLevel = 2; + } + pARMSOC->dri3_available = FALSE; + pARMSOC->dri3_override = FALSE; + pARMSOC->dri3_enable = FALSE; + pARMSOC->dri3 = FALSE; + pARMSOC->dri2_available = FALSE; + pARMSOC->dri2_enable = FALSE; + pARMSOC->dri2 = FALSE; + pARMSOC->dri2DriverName = pARMSOC->drmmode_interface->driver_name; + + + pARMSOC->dri3_available = !!xf86LoadSubModule(pScrn, "dri3"); + if (pARMSOC->dri3_available) + INFO_MSG("LoadModule: dri3 success"); + else + WARNING_MSG("LoadModule: dri3 error"); + pARMSOC->dri3_override = + !pARMSOC->dri3_available || + xf86IsOptionSet(pARMSOC->pOptionInfo, OPTION_DRI_LEVEL); + + if (driLevel >= 3) + pARMSOC->dri3_enable = pARMSOC->dri3_available; + + pARMSOC->dri2_available = !!xf86LoadSubModule(pScrn, "dri2"); + if (pARMSOC->dri2_available) + INFO_MSG("LoadModule: dri2 success"); + else + WARNING_MSG("LoadModule: dri2 error"); + if (driLevel >= 2) + pARMSOC->dri2_enable = pARMSOC->dri2_available; + +  ARMSOCAccelInit struct ARMSOCRec の DRI2と DRI3 を管理するためのメンバー変数の値に基づいて DRI3 および DRI2 の初期化関数を呼び出します。 src/armsoc_driver.c /** - * Initialize EXA and DRI2 + * Initialize EXA and DRI2 and DRI3 */ static void ARMSOCAccelInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn); + char str[128] = ""; if (!pARMSOC->pARMSOCEXA) pARMSOC->pARMSOCEXA = InitNullEXA(pScreen, pScrn, pARMSOC->drmFD); + if (!pARMSOC->pARMSOCEXA) + return; + + if (pARMSOC->dri2_enable) + pARMSOC->dri2 = ARMSOCDRI2ScreenInit(pScreen); + + if (pARMSOC->dri2) + strcat(str, "DRI2 "); + + if (pARMSOC->dri3_enable || (!pARMSOC->dri2 && !pARMSOC->dri3_override)) + pARMSOC->dri3 = ARMSOCDRI3ScreenInit(pScreen); - if (pARMSOC->pARMSOCEXA) - pARMSOC->dri = ARMSOCDRI2ScreenInit(pScreen); + if (pARMSOC->dri3) + strcat(str, "DRI3 "); + + if (*str) + INFO_MSG("direct rendering: %senabled", str); else - pARMSOC->dri = FALSE; + INFO_MSG("direct rendering: disabled"); }  ARMSOCScreenInit 失敗時の処理を修正します。 src/armsoc_driver.c @@ -1190,12 +1241,20 @@ fail6: drmmode_cursor_fini(pScreen); fail5: - if (pARMSOC->dri) + if (pARMSOC->dri3) { + pARMSOC->dri3 = FALSE; + } + + if (pARMSOC->dri2) { ARMSOCDRI2CloseScreen(pScreen); + pARMSOC->dri2 = FALSE; + } - if (pARMSOC->pARMSOCEXA) + if (pARMSOC->pARMSOCEXA) { if (pARMSOC->pARMSOCEXA->CloseScreen) pARMSOC->pARMSOCEXA->CloseScreen(CLOSE_SCREEN_ARGS); + pARMSOC->pARMSOCEXA = FALSE; + } fail4: /* Call the CloseScreen functions for fbInitScreen, miDCInitialize, * exaDriverInit & xf86CrtcScreenInit as appropriate via their  ARMSOCCloseScreen 終了時の処理を修正します。 src/armsoc_driver.c @@ -1270,12 +1329,19 @@ ARMSOCCloseScreen(CLOSE_SCREEN_ARGS_DECL) ret = (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); - if (pARMSOC->dri) + if (pARMSOC->dri3) + pARMSOC->dri3 = FALSE; + + if (pARMSOC->dri2) { ARMSOCDRI2CloseScreen(pScreen); + pARMSOC->dri2 = FALSE; + } - if (pARMSOC->pARMSOCEXA) + if (pARMSOC->pARMSOCEXA) { if (pARMSOC->pARMSOCEXA->CloseScreen) pARMSOC->pARMSOCEXA->CloseScreen(CLOSE_SCREEN_ARGS); + pARMSOC->pARMSOCEXA = FALSE; + } assert(pARMSOC->scanout); /* Screen drops its ref on the scanout buffer */ 参考 Lima web (https://gitlab.freedesktop.org/lima/web) Mesa 3D and Direct Rendering Infrastructure wiki (https://dri.freedesktop.org/wiki) https://github.com/ikwzm/ZynqMP-FPGA-Ubuntu20.04-Lima-Ultra96 https://github.com/ikwzm/xf86-video-armsoc-xilinx
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ZYNQのLinuxアプリをVSCodeでデバッグする方法

前編の ZYNQのLinuxアプリをVSCodeでビルドする方法 でビルド方法を紹介したので、次はデバッグできるようにしましょう。 VSCode側の設定 C++のプログラムを編集している画面でF5を押します。Launchのキーだそうですが、launchがまだ設定されていないので下のようなメニューが開きます。GDBかWindowsかはどちらでもいい(どうせ後で書き換えるから)のですが、とりあえずはC++ (GDB/LLDB) を選んでおきましょう。 launch.json が作られるので、以下のように書き換えます。 launch.json { // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "Remote unit test", "type": "cppdbg", "request": "launch", "program": "${fileDirname}\\${fileBasenameNoExtension}.elf", "MIMode": "gdb", "miDebuggerPath": "D:/Xilinx/SDK/2018.3/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-gdb.exe", "miDebuggerServerAddress": "cszmini:9999", "args": [], "cwd": "${workspaceFolder}", "stopAtEntry": false, "setupCommands": [ { "description": "gdb の再フォーマットを有効にする", "text": "-enable-pretty-printing", "ignoreFailures": true } ] }, ] } 環境に応じて書き換えるべきポイントは以下の2点です。 デバッガのパスの設定 Windows上のARM用GDBのパスを指定します。 "miDebuggerPath": "D:/Xilinx/SDK/2018.3/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-gdb.exe", ターゲットのアドレスの設定 ターゲットのIPアドレス(またはホスト名)と、ポート番号を指定します。 "miDebuggerServerAddress": "cszmini:9999", "miDebuggerServerAddress": "192.168.1.4:12345", のようにします。 とりあえず実行 F5を押すとlaunchに書かれたコマンドが実行されます。この時点ではターゲットボードでLinuxは動いていないのでエラーダイアログが出ます。 Linux側の準備 apt install gdbserverで、gdbserverをインストールしておきます。 Linuxのシェル上で、 # gdbserver localhost:9999 ./test.elf と入力します。上のコマンドはgdbserverを起動して、ポート9999で待ち受けてtest.elfをアタッチします。 VSCodeでいざLaunch いよいよVSCodeでF5を押してデバッグ開始です。 VSCode上でgdbが起動し、リモートのターゲットボードに接続されます。ステップ実行や変数の参照ができ、デバッグできるようになります。 対するLinux側ではプログラムがリモート操作されてステップ実行されています。 プログラムが終了するか、VSCodeで □ を押すと終了します。 もっと便利にしたい ユーザ作成のライブラリを使う ユーザが作成したライブラリを使うには、プロジェクトのフォルダにライブラリを入れ、tasks.jsonのargsに-Lと-lオプションを追加します。次の設定ではcszapiというライブラリが使われるようになります。 "args": [ "-g", "${file}", "-L${workspaceFolder}", "-lcszapi", "-o", "${fileDirname}\\${fileBasenameNoExtension}.elf" ], また、ヘッダファイルのIntelliSenseが動くようにするにはc_cpp_properties.jsonを編集して、インクルードパスを通すようにします。 これでユーザ作成のライブラリが使えるようになります。 ビルドが終わったら自動的にターゲットにコピーしたい クロスコンパイルなので、出来上がったプログラムはターゲットボード上にコピーしなければなりません。毎回毎回scpや、エクスプローラでCTRL+C,CTRL+Vするのも面倒なので、tasks.jsonに自動化の処理を書いてあげましょう。 tasks.jsonは、"tasks": [で複数のタスクを登録できるようになっていますが、"group": { "kind": "build", "isDefault": true}が付いているタスクが CTRL*SHIFT+B で実行されるようになっています。 また、各タスクには "dependsOn": というパラメータが設定できて、これを使うとタスクの依存関係を設定できます。 つまり、ターゲットボード上にファイルを転送するというDeployというisDefaultなタスクを作り、DeployはBuildに依存するようにすれば、CTRL+SHIFT+Bでビルドとファイルコピーが可能になります。 (自動Deploy版)tasks.json { // tasks.json 形式の詳細についての資料は、 // https://go.microsoft.com/fwlink/?LinkId=733558 をご覧ください "version": "2.0.0", "tasks": [ { "label": "Deploy", "type": "shell", "command": "cp", "args": [ "${fileDirname}\\${fileBasenameNoExtension}.elf", "\\\\cszmini\\Share" ], "problemMatcher": [], "dependsOn": "Build by ARM g++", "group": { "kind": "build", "isDefault": true } }, { "type": "shell", "label": "Build by ARM g++", "command": "D:/Xilinx/SDK/2018.3/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-g++.exe", "args": [ "-g", "${file}", "-L${workspaceFolder}", "-lcszapi", "-o", "${fileDirname}\\${fileBasenameNoExtension}.elf" ], "options": { "cwd": "D:/Xilinx/SDK/2019.1/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin" }, "problemMatcher": [ "$gcc" ], "group": "build" } ] } dependsOnの参照はlabelを使って行われるようです。 F5でビルドとgdbの起動ができるようにしたい launch.jsonのconfigurationsに登録されたタスクに、"preLaunchTask":というパラメータを設定しておけば、このタスクが実行される前に実行すべきタスクを指定できます。 したがって、"preLaunchTask": "Deploy"と書けば、GDB接続の前にDeployタスクが実行されて、ビルドとファイルの転送が行われます。 しかし、Linux上ではgdbserverプロセスを走らせなければならないのですが、このgdbserverを起動する前にtest.elfはターゲットボード上になければなりません。また、gdbserverを停止するにはリモートで接続してプログラムが終了するかkillするしかなく、ちょっと面倒です。 結論を言うと、preLaunchTaskを書いてビルドを自動実行するのではなく、リモートデバッグの場合は「ビルド&ファイル転送」と「デバッガ起動」は分けたほうがいいです。 少々面倒ですが、プログラムを書いてからそれを実行するまでに CTRL+SHIFT+Bでビルド&実行ファイル転送 Linux上でgdbserver起動 F5でデバッグ開始 と、3ステップ必要です。gdbは巨大なプログラムだから、ちゃんと調べればファイル転送できるのかな? GLIBCのバージョンが合わないとどうなる? GLIBCのバージョンが合わない場合、つまりUbuntu 14のシステムをXSDK 2019.1に入っているarm-linux-gnueabihf-gdbでデバッグしようとすると、 readchar: Got EOF というエラーが出てGDBが接続できません。 実際にやってみると こうなります。 まとめ VSCodeでZYNQのLinuxで動くARMのプログラムが書けて、デバッグまでできるようになりました。 これでXSDKを卒業できるかな!?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ZYNQのLinuxアプリをVSCodeでビルドする方法

VSCodeを使ってZYNQのLinuxで動くプログラムをビルドし、さらにデバッグまですることができたので、そのやり方を紹介します。 用意するもの Linuxが動くZYNQのボード (Cosmo-Z とか Zynqberry とか・・) VSCode と C/C++拡張 LAN接続。sambaでファイル共有すると便利 ZYNQ上で動作するgdbserver XILINX SDK (XSDK) VSCodeのインストールとC/C++拡張 まずVSCodeをインストールし、C/C++拡張wインストールします。 特に説明は不要かと思います。 XILINX SDKのインストール ZYNQで動くLinuxに入っているGLIBCのバージョンが2.19とかならXSDK2018.3以前を、2.27とかならXSDK2019.1以降を選びます。 ややこしいのですが、詳しくは 「XILINX SDKをアップデートしたらGLIBCのバージョン相違で動かない」 を参照してください。 熱心なXILINXユーザならいろんなバージョンのツールが入っているから大丈夫だと思います。 プロジェクトのフォルダを作ってVSCodeで開く VSCodeで作業するためのフォルダを作り、VSCodeでOpen Folderで開きます。 ここでは D:\naitou\vstest としておきます。 C/C++ファイルの設定をする 私自身がVSCodeを使い始めて間もないのでよくわかっていませんが、CTRL+SHIFT+Pでプルダウンが開いたら、C++と打って、C/C++: Edit Confiturations (UI)を開きます。 C/C++拡張の設定が開くので、構成名のところにArmLinuxとか適当な名前を付けます。 コンパイラパスには、XSDKのarm-linux-gnueabihf-gcc.exeへのパスを指定します。 私の環境では D:\Xilinx\SDK\2018.3\gnu\aarch32\nt\gcc-arm-linux-gnueabi\bin\arm-linux-gnueabihf-gcc.exe です。ターゲットのLinuxのGLIBCのバージョンに合わせてXSDKのバージョンを変えてください。 IntelliSenseモードをlinux-gcc-armにして、インクルードパスには、XSDKのディレクトリの中のincludeパスを指定しておきます。 D:/Xilinx/SDK/2018.3/gnu/aarch32/nt/gcc-arm-linux-gnueabi/arm-linux-gnueabihf/libc/usr/include/** これで.vscodeフォルダの中にc_cpp_properties.json というファイルが作られているはずです。 c_cpp_properties.json { "configurations": [ { "name": "ArmLinux", "includePath": [ "${workspaceFolder}/**", "D:/Xilinx/SDK/2018.3/gnu/aarch32/nt/gcc-arm-linux-gnueabi/arm-linux-gnueabihf/libc/usr/include/**" ], "defines": [ "_DEBUG", "UNICODE", "_UNICODE" ], "windowsSdkVersion": "10.0.19041.0", "compilerPath": "D:/Xilinx/SDK/2018.3/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-gcc.exe", "cStandard": "c17", "cppStandard": "c++17", "intelliSenseMode": "linux-gcc-arm" } ], "version": 4 } これはコード補完や、テキストエディタ上でのWarningを出すための設定なので、実際に使われるコンパイラとは違っていてもいいのだと思います。 タスクの設定 次に、VSCodeに戻ってCTRL+SHIFT+Pを押しbuildと打ちます。候補が出てくるのでTasks:Configure Default Buld Taskを選びます。 この時点ではcl.exeを使うものが出てくるので、それを選びます。 そうしたら、tasks.jsonがcl.exeを使うように出来ているのでいったん全部消して、gccを使うように変更します。 tasks.json { // tasks.json 形式の詳細についての資料は、 // https://go.microsoft.com/fwlink/?LinkId=733558 をご覧ください "version": "2.0.0", "tasks": [ { "type": "shell", "label": "Build by ARM g++", "command": "D:/Xilinx/SDK/2018.3/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-g++.exe", "args": [ "-g", "${file}", "-o", "${fileDirname}\\${fileBasenameNoExtension}.elf" ], "options": { "cwd": "D:/Xilinx/SDK/2018.3/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin" }, "problemMatcher": [ "$gcc" ], "group": { "kind": "build", "isDefault": true } } ] } commandのパスはXSDKをインストールしたフォルダに合わせてください。cwdは${workspaceFolder}でもいいかもしれません。 適当なプログラムを書く ファイルを新規作成して、ビルドしましょう。 test.cpp #include <stdio.h> int main() { printf("Hello World, Zynq!\n"); for(int i = 0 ; i < 100 ; i++) { printf("%d\n" , i); } return 0; } ビルド VSCodeでCTRL+SHIFT+Bを押すとtasks.jsonに書かれたタスクのうち、 "group": { "kind": "build", "isDefault": true } が指定されたタスクが実行されます。今回は"Build by ARM g++"というタスクで、"command"で指定されたg++のプログラムが実行されます。VSCodeの下段にあるTerminalにビルド結果が表示されます。コンパイルエラーもここに表示されます。 実行 出来上がったプログラム、test.elf ををZYNQのLinuxに転送します。 SCPとか意識高いコマンドを使ってもいいですが、私はsambaで共有させておいてWindowsのExplorerでファイルコピーするのが好きです。もしくはZYNQ Linux上にsambaで共有するフォルダを作って、その上にVSCodeにプロジェクトフォルダを作ってもいいかもしれませんね。 そして、Linuxにログインしたら実行してみましょう! まとめ c_cpp_properties.json にはファイルの属性などが書かれる。 tasks.json にはビルドするためのコマンドの起動方法が書かれる。 感想 はじめてVSCodeでエディタ以上の使い方をしてみようと思ったのですが、無事に動いてよかったです。 これでもうXSDKやVitisのEclipse環境から抜けられるかも!? ↓↓↓↓↓↓↓↓ 続く デバッグ編に続く ↑↑↑↑↑↑↑↑ 続く
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LinuxのUSBインストールの方法(Mac用)

これは自分用の備忘録です。 まずはターミナルを開く。 USBデバイスを接続 $ diskutil list /dev/disk3 (external, physical): #: TYPE NAME SIZE IDENTIFIER 0: FDisk_partition_scheme *15.5 GB disk3 1: 0xEF ⁨⁩ 9.0 MB disk3s2 /dev/disk3の場所は人によって変わるので要確認 $ diskutil eraseDisk MS-DOS UNTITLED /dev/disk3 Unmounting disk Creating the partition map Waiting for partitions to activate Formatting disk3s2 as MS-DOS (FAT) with name UNTITLED 512 bytes per physical sector /dev/rdisk3s2: 29867504 sectors in 1866719 FAT32 clusters (8192 bytes/cluster) bps=512 spc=16 res=32 nft=2 mid=0xf8 spt=32 hds=255 hid=411648 drv=0x80 bsec=29896704 bspf=14584 rdcl=2 infs=1 bkbs=6 Mounting disk Finished erase on disk3 マウントしている状態だとダメなのでアンマウントする $ diskutil unmountDisk /dev/disk3 Unmount of all volumes on disk3 was successful ISOファイルをダウンロードしたディレクトリに移動する。 移動しないと次のコマンドでエラーになる 今回の場合はデスクトップ $ cd Desktop/ 最後にUSBに移す $ sudo dd if=CentOS-7-x86_64-Minimal-2009.iso of=/dev/disk3 bs=1m 973+0 records in 973+0 records out 1020264448 bytes transferred in 88.235467 secs (11562974 bytes/sec) CentOS-7-x86_64-Minimal-2009.isoこの部分は自分のインストールしたファイルによって変更する 使ったlinux : http://ftp.riken.jp/Linux/centos/7.9.2009/isos/x86_64/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む