From 2c3c1048746a4622d8c89a29670120dc8fab93c4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:49:45 +0200 Subject: Adding upstream version 6.1.76. Signed-off-by: Daniel Baumann --- Documentation/translations/index.rst | 58 + .../translations/it_IT/admin-guide/README.rst | 12 + .../it_IT/admin-guide/kernel-parameters.rst | 12 + .../it_IT/admin-guide/security-bugs.rst | 12 + .../translations/it_IT/core-api/index.rst | 18 + .../it_IT/core-api/memory-allocation.rst | 13 + .../it_IT/core-api/symbol-namespaces.rst | 166 ++ .../devicetree/bindings/submitting-patches.rst | 11 + .../translations/it_IT/disclaimer-ita.rst | 6 + .../translations/it_IT/doc-guide/index.rst | 24 + .../translations/it_IT/doc-guide/kernel-doc.rst | 561 ++++ .../translations/it_IT/doc-guide/parse-headers.rst | 196 ++ .../translations/it_IT/doc-guide/sphinx.rst | 489 ++++ Documentation/translations/it_IT/index.rst | 141 + .../translations/it_IT/kernel-hacking/hacking.rst | 870 ++++++ .../translations/it_IT/kernel-hacking/index.rst | 16 + .../translations/it_IT/kernel-hacking/locking.rst | 1495 ++++++++++ .../it_IT/maintainer/configure-git.rst | 10 + .../translations/it_IT/networking/netdev-FAQ.rst | 13 + .../translations/it_IT/process/1.Intro.rst | 297 ++ .../translations/it_IT/process/2.Process.rst | 534 ++++ .../translations/it_IT/process/3.Early-stage.rst | 242 ++ .../translations/it_IT/process/4.Coding.rst | 446 +++ .../translations/it_IT/process/5.Posting.rst | 364 +++ .../translations/it_IT/process/6.Followthrough.rst | 240 ++ .../it_IT/process/7.AdvancedTopics.rst | 191 ++ .../translations/it_IT/process/8.Conclusion.rst | 84 + .../translations/it_IT/process/adding-syscalls.rst | 643 +++++ .../it_IT/process/applying-patches.rst | 15 + .../translations/it_IT/process/changes.rst | 517 ++++ .../translations/it_IT/process/clang-format.rst | 197 ++ .../translations/it_IT/process/code-of-conduct.rst | 12 + .../translations/it_IT/process/coding-style.rst | 1213 ++++++++ .../translations/it_IT/process/deprecated.rst | 384 +++ .../it_IT/process/development-process.rst | 33 + .../translations/it_IT/process/email-clients.rst | 341 +++ Documentation/translations/it_IT/process/howto.rst | 642 +++++ Documentation/translations/it_IT/process/index.rst | 69 + .../translations/it_IT/process/kernel-docs.rst | 18 + .../it_IT/process/kernel-driver-statement.rst | 211 ++ .../it_IT/process/kernel-enforcement-statement.rst | 175 ++ .../translations/it_IT/process/license-rules.rst | 500 ++++ .../translations/it_IT/process/magic-number.rst | 91 + .../it_IT/process/maintainer-handbooks.rst | 24 + .../it_IT/process/maintainer-pgp-guide.rst | 949 +++++++ .../translations/it_IT/process/maintainer-tip.rst | 10 + .../translations/it_IT/process/maintainers.rst | 13 + .../it_IT/process/management-style.rst | 295 ++ .../it_IT/process/programming-language.rst | 53 + .../it_IT/process/stable-api-nonsense.rst | 209 ++ .../it_IT/process/stable-kernel-rules.rst | 216 ++ .../it_IT/process/submit-checklist.rst | 132 + .../it_IT/process/submitting-patches.rst | 817 ++++++ .../it_IT/process/volatile-considered-harmful.rst | 134 + .../translations/it_IT/riscv/patch-acceptance.rst | 40 + Documentation/translations/ja_JP/SubmitChecklist | 105 + Documentation/translations/ja_JP/SubmittingPatches | 721 +++++ Documentation/translations/ja_JP/howto.rst | 650 +++++ Documentation/translations/ja_JP/index.rst | 18 + .../translations/ja_JP/stable_api_nonsense.txt | 263 ++ .../translations/ja_JP/stable_kernel_rules.txt | 84 + Documentation/translations/ko_KR/howto.rst | 619 +++++ Documentation/translations/ko_KR/index.rst | 29 + .../translations/ko_KR/memory-barriers.txt | 2931 ++++++++++++++++++++ .../translations/ko_KR/stable_api_nonsense.txt | 195 ++ Documentation/translations/zh_CN/PCI/acpi-info.rst | 139 + Documentation/translations/zh_CN/PCI/index.rst | 34 + Documentation/translations/zh_CN/PCI/msi-howto.rst | 233 ++ .../translations/zh_CN/PCI/pci-iov-howto.rst | 169 ++ Documentation/translations/zh_CN/PCI/pci.rst | 514 ++++ .../translations/zh_CN/PCI/pciebus-howto.rst | 192 ++ Documentation/translations/zh_CN/PCI/sysfs-pci.rst | 126 + .../zh_CN/accounting/delay-accounting.rst | 109 + .../translations/zh_CN/accounting/index.rst | 25 + .../translations/zh_CN/accounting/psi.rst | 155 ++ .../translations/zh_CN/accounting/taskstats.rst | 145 + .../translations/zh_CN/admin-guide/README.rst | 291 ++ .../translations/zh_CN/admin-guide/bootconfig.rst | 293 ++ .../translations/zh_CN/admin-guide/bug-bisect.rst | 81 + .../translations/zh_CN/admin-guide/bug-hunting.rst | 340 +++ .../zh_CN/admin-guide/clearing-warn-once.rst | 9 + .../translations/zh_CN/admin-guide/cpu-load.rst | 105 + .../translations/zh_CN/admin-guide/cputopology.rst | 96 + .../translations/zh_CN/admin-guide/index.rst | 133 + .../translations/zh_CN/admin-guide/init.rst | 54 + .../zh_CN/admin-guide/lockup-watchdogs.rst | 66 + .../zh_CN/admin-guide/mm/damon/index.rst | 28 + .../zh_CN/admin-guide/mm/damon/reclaim.rst | 232 ++ .../zh_CN/admin-guide/mm/damon/start.rst | 132 + .../zh_CN/admin-guide/mm/damon/usage.rst | 559 ++++ .../translations/zh_CN/admin-guide/mm/index.rst | 49 + .../translations/zh_CN/admin-guide/mm/ksm.rst | 148 + .../zh_CN/admin-guide/reporting-issues.rst | 1368 +++++++++ .../zh_CN/admin-guide/reporting-regressions.rst | 370 +++ .../zh_CN/admin-guide/security-bugs.rst | 74 + .../translations/zh_CN/admin-guide/sysrq.rst | 280 ++ .../zh_CN/admin-guide/tainted-kernels.rst | 157 ++ .../translations/zh_CN/admin-guide/unicode.rst | 170 ++ Documentation/translations/zh_CN/arch.rst | 29 + Documentation/translations/zh_CN/arm/Booting | 175 ++ .../translations/zh_CN/arm/kernel_user_helpers.txt | 284 ++ Documentation/translations/zh_CN/arm64/amu.rst | 100 + Documentation/translations/zh_CN/arm64/booting.txt | 246 ++ .../translations/zh_CN/arm64/elf_hwcaps.rst | 240 ++ .../translations/zh_CN/arm64/hugetlbpage.rst | 45 + Documentation/translations/zh_CN/arm64/index.rst | 19 + .../zh_CN/arm64/legacy_instructions.txt | 72 + Documentation/translations/zh_CN/arm64/memory.txt | 114 + Documentation/translations/zh_CN/arm64/perf.rst | 86 + .../translations/zh_CN/arm64/silicon-errata.txt | 74 + .../translations/zh_CN/arm64/tagged-pointers.txt | 52 + .../translations/zh_CN/core-api/assoc_array.rst | 473 ++++ .../translations/zh_CN/core-api/boot-time-mm.rst | 49 + .../translations/zh_CN/core-api/cachetlb.rst | 333 +++ .../zh_CN/core-api/circular-buffers.rst | 210 ++ .../translations/zh_CN/core-api/cpu_hotplug.rst | 667 +++++ .../translations/zh_CN/core-api/genalloc.rst | 109 + .../zh_CN/core-api/generic-radix-tree.rst | 23 + .../translations/zh_CN/core-api/genericirq.rst | 409 +++ .../zh_CN/core-api/gfp_mask-from-fs-io.rst | 66 + Documentation/translations/zh_CN/core-api/idr.rst | 80 + .../translations/zh_CN/core-api/index.rst | 147 + .../translations/zh_CN/core-api/irq/concepts.rst | 26 + .../translations/zh_CN/core-api/irq/index.rst | 22 + .../zh_CN/core-api/irq/irq-affinity.rst | 78 + .../translations/zh_CN/core-api/irq/irq-domain.rst | 243 ++ .../zh_CN/core-api/irq/irqflags-tracing.rst | 47 + .../translations/zh_CN/core-api/kernel-api.rst | 372 +++ .../translations/zh_CN/core-api/kobject.rst | 379 +++ Documentation/translations/zh_CN/core-api/kref.rst | 311 +++ .../translations/zh_CN/core-api/local_ops.rst | 196 ++ .../zh_CN/core-api/memory-allocation.rst | 138 + .../translations/zh_CN/core-api/memory-hotplug.rst | 122 + .../translations/zh_CN/core-api/mm-api.rst | 131 + .../translations/zh_CN/core-api/packing.rst | 160 ++ .../translations/zh_CN/core-api/padata.rst | 161 ++ .../translations/zh_CN/core-api/printk-basics.rst | 111 + .../translations/zh_CN/core-api/printk-formats.rst | 598 ++++ .../zh_CN/core-api/protection-keys.rst | 99 + .../translations/zh_CN/core-api/rbtree.rst | 391 +++ .../zh_CN/core-api/refcount-vs-atomic.rst | 156 ++ .../zh_CN/core-api/symbol-namespaces.rst | 144 + .../zh_CN/core-api/unaligned-memory-access.rst | 229 ++ .../translations/zh_CN/core-api/watch_queue.rst | 313 +++ .../translations/zh_CN/core-api/workqueue.rst | 352 +++ .../translations/zh_CN/core-api/xarray.rst | 373 +++ Documentation/translations/zh_CN/cpu-freq/core.rst | 109 + .../translations/zh_CN/cpu-freq/cpu-drivers.rst | 257 ++ .../translations/zh_CN/cpu-freq/cpufreq-stats.rst | 133 + .../translations/zh_CN/cpu-freq/index.rst | 47 + .../translations/zh_CN/dev-tools/gcov.rst | 264 ++ .../zh_CN/dev-tools/gdb-kernel-debugging.rst | 167 ++ .../translations/zh_CN/dev-tools/index.rst | 40 + .../translations/zh_CN/dev-tools/kasan.rst | 454 +++ .../translations/zh_CN/dev-tools/sparse.rst | 110 + .../zh_CN/dev-tools/testing-overview.rst | 134 + .../translations/zh_CN/devicetree/changesets.rst | 37 + .../zh_CN/devicetree/dynamic-resolution-notes.rst | 31 + .../translations/zh_CN/devicetree/index.rst | 45 + .../translations/zh_CN/devicetree/kernel-api.rst | 58 + .../translations/zh_CN/devicetree/of_unittest.rst | 189 ++ .../zh_CN/devicetree/overlay-notes.rst | 140 + .../translations/zh_CN/devicetree/usage-model.rst | 330 +++ .../translations/zh_CN/disclaimer-zh_CN.rst | 9 + .../translations/zh_CN/doc-guide/contributing.rst | 238 ++ .../translations/zh_CN/doc-guide/index.rst | 27 + .../translations/zh_CN/doc-guide/kernel-doc.rst | 499 ++++ .../zh_CN/doc-guide/maintainer-profile.rst | 43 + .../translations/zh_CN/doc-guide/parse-headers.rst | 187 ++ .../translations/zh_CN/doc-guide/sphinx.rst | 412 +++ .../translations/zh_CN/driver-api/gpio/index.rst | 69 + .../translations/zh_CN/driver-api/gpio/legacy.rst | 694 +++++ .../translations/zh_CN/driver-api/index.rst | 132 + .../translations/zh_CN/driver-api/io_ordering.rst | 60 + .../translations/zh_CN/filesystems/debugfs.rst | 221 ++ .../translations/zh_CN/filesystems/index.rst | 29 + .../translations/zh_CN/filesystems/sysfs.txt | 373 +++ .../translations/zh_CN/filesystems/tmpfs.rst | 146 + .../translations/zh_CN/filesystems/virtiofs.rst | 58 + .../translations/zh_CN/iio/ep93xx_adc.rst | 48 + .../translations/zh_CN/iio/iio_configfs.rst | 106 + Documentation/translations/zh_CN/iio/index.rst | 22 + Documentation/translations/zh_CN/index.rst | 142 + .../translations/zh_CN/infiniband/core_locking.rst | 115 + .../translations/zh_CN/infiniband/index.rst | 40 + .../translations/zh_CN/infiniband/ipoib.rst | 111 + .../translations/zh_CN/infiniband/opa_vnic.rst | 156 ++ .../translations/zh_CN/infiniband/sysfs.rst | 21 + .../translations/zh_CN/infiniband/tag_matching.rst | 63 + .../translations/zh_CN/infiniband/user_mad.rst | 164 ++ .../translations/zh_CN/infiniband/user_verbs.rst | 72 + .../translations/zh_CN/kernel-hacking/hacking.rst | 707 +++++ .../translations/zh_CN/kernel-hacking/index.rst | 22 + Documentation/translations/zh_CN/locking/index.rst | 43 + .../translations/zh_CN/locking/mutex-design.rst | 145 + .../translations/zh_CN/locking/spinlocks.rst | 149 + .../translations/zh_CN/loongarch/booting.rst | 48 + .../translations/zh_CN/loongarch/features.rst | 8 + .../translations/zh_CN/loongarch/index.rst | 27 + .../translations/zh_CN/loongarch/introduction.rst | 353 +++ .../zh_CN/loongarch/irq-chip-model.rst | 157 ++ .../zh_CN/maintainer/configure-git.rst | 62 + .../translations/zh_CN/maintainer/index.rst | 21 + .../zh_CN/maintainer/maintainer-entry-profile.rst | 92 + .../zh_CN/maintainer/modifying-patches.rst | 51 + .../zh_CN/maintainer/pull-requests.rst | 148 + .../zh_CN/maintainer/rebasing-and-merging.rst | 165 ++ Documentation/translations/zh_CN/mips/booting.rst | 34 + Documentation/translations/zh_CN/mips/features.rst | 13 + Documentation/translations/zh_CN/mips/index.rst | 29 + .../translations/zh_CN/mips/ingenic-tcu.rst | 72 + Documentation/translations/zh_CN/mm/active_mm.rst | 85 + Documentation/translations/zh_CN/mm/balance.rst | 81 + Documentation/translations/zh_CN/mm/damon/api.rst | 32 + .../translations/zh_CN/mm/damon/design.rst | 140 + Documentation/translations/zh_CN/mm/damon/faq.rst | 48 + .../translations/zh_CN/mm/damon/index.rst | 32 + .../translations/zh_CN/mm/free_page_reporting.rst | 38 + Documentation/translations/zh_CN/mm/frontswap.rst | 196 ++ Documentation/translations/zh_CN/mm/highmem.rst | 137 + Documentation/translations/zh_CN/mm/hmm.rst | 361 +++ .../translations/zh_CN/mm/hugetlbfs_reserv.rst | 436 +++ Documentation/translations/zh_CN/mm/hwpoison.rst | 166 ++ Documentation/translations/zh_CN/mm/index.rst | 69 + Documentation/translations/zh_CN/mm/ksm.rst | 70 + .../translations/zh_CN/mm/memory-model.rst | 135 + .../translations/zh_CN/mm/mmu_notifier.rst | 97 + Documentation/translations/zh_CN/mm/numa.rst | 101 + .../zh_CN/mm/overcommit-accounting.rst | 86 + Documentation/translations/zh_CN/mm/page_frags.rst | 38 + .../translations/zh_CN/mm/page_migration.rst | 228 ++ Documentation/translations/zh_CN/mm/page_owner.rst | 181 ++ .../translations/zh_CN/mm/page_table_check.rst | 56 + .../translations/zh_CN/mm/remap_file_pages.rst | 32 + .../zh_CN/mm/split_page_table_lock.rst | 96 + .../zh_CN/mm/vmalloced-kernel-stacks.rst | 133 + Documentation/translations/zh_CN/mm/z3fold.rst | 31 + Documentation/translations/zh_CN/mm/zsmalloc.rst | 78 + .../translations/zh_CN/openrisc/index.rst | 32 + .../translations/zh_CN/openrisc/openrisc_port.rst | 127 + Documentation/translations/zh_CN/openrisc/todo.rst | 23 + .../translations/zh_CN/parisc/debugging.rst | 45 + Documentation/translations/zh_CN/parisc/index.rst | 31 + .../translations/zh_CN/parisc/registers.rst | 156 ++ Documentation/translations/zh_CN/peci/index.rst | 26 + Documentation/translations/zh_CN/peci/peci.rst | 54 + .../translations/zh_CN/power/energy-model.rst | 190 ++ Documentation/translations/zh_CN/power/index.rst | 56 + Documentation/translations/zh_CN/power/opp.rst | 341 +++ .../translations/zh_CN/process/1.Intro.rst | 195 ++ .../translations/zh_CN/process/2.Process.rst | 365 +++ .../translations/zh_CN/process/3.Early-stage.rst | 168 ++ .../translations/zh_CN/process/4.Coding.rst | 293 ++ .../translations/zh_CN/process/5.Posting.rst | 246 ++ .../translations/zh_CN/process/6.Followthrough.rst | 152 + .../zh_CN/process/7.AdvancedTopics.rst | 133 + .../translations/zh_CN/process/8.Conclusion.rst | 69 + .../process/code-of-conduct-interpretation.rst | 108 + .../translations/zh_CN/process/code-of-conduct.rst | 72 + .../translations/zh_CN/process/coding-style.rst | 1083 ++++++++ .../zh_CN/process/development-process.rst | 26 + .../translations/zh_CN/process/email-clients.rst | 327 +++ .../zh_CN/process/embargoed-hardware-issues.rst | 228 ++ Documentation/translations/zh_CN/process/howto.rst | 495 ++++ Documentation/translations/zh_CN/process/index.rst | 63 + .../zh_CN/process/kernel-driver-statement.rst | 199 ++ .../zh_CN/process/kernel-enforcement-statement.rst | 151 + .../translations/zh_CN/process/license-rules.rst | 370 +++ .../translations/zh_CN/process/magic-number.rst | 74 + .../zh_CN/process/management-style.rst | 207 ++ .../zh_CN/process/programming-language.rst | 71 + .../zh_CN/process/stable-api-nonsense.rst | 155 ++ .../zh_CN/process/stable-kernel-rules.rst | 64 + .../zh_CN/process/submit-checklist.rst | 111 + .../zh_CN/process/submitting-patches.rst | 657 +++++ .../zh_CN/process/volatile-considered-harmful.rst | 106 + .../translations/zh_CN/riscv/boot-image-header.rst | 69 + Documentation/translations/zh_CN/riscv/index.rst | 30 + .../translations/zh_CN/riscv/patch-acceptance.rst | 33 + .../translations/zh_CN/riscv/vm-layout.rst | 104 + .../translations/zh_CN/scheduler/completion.rst | 256 ++ .../translations/zh_CN/scheduler/index.rst | 45 + .../translations/zh_CN/scheduler/sched-arch.rst | 76 + .../translations/zh_CN/scheduler/sched-bwc.rst | 204 ++ .../zh_CN/scheduler/sched-capacity.rst | 390 +++ .../translations/zh_CN/scheduler/sched-debug.rst | 51 + .../zh_CN/scheduler/sched-design-CFS.rst | 205 ++ .../translations/zh_CN/scheduler/sched-domains.rst | 72 + .../translations/zh_CN/scheduler/sched-energy.rst | 351 +++ .../zh_CN/scheduler/sched-nice-design.rst | 99 + .../translations/zh_CN/scheduler/sched-stats.rst | 156 ++ .../translations/zh_CN/scheduler/schedutil.rst | 165 ++ .../translations/zh_CN/sound/hd-audio/controls.rst | 102 + .../translations/zh_CN/sound/hd-audio/index.rst | 14 + Documentation/translations/zh_CN/sound/index.rst | 22 + .../translations/zh_CN/video4linux/omap3isp.txt | 277 ++ .../zh_CN/video4linux/v4l2-framework.txt | 976 +++++++ .../translations/zh_CN/virt/acrn/cpuid.rst | 56 + .../translations/zh_CN/virt/acrn/index.rst | 25 + .../translations/zh_CN/virt/acrn/introduction.rst | 52 + .../translations/zh_CN/virt/acrn/io-request.rst | 99 + .../translations/zh_CN/virt/guest-halt-polling.rst | 87 + Documentation/translations/zh_CN/virt/index.rst | 38 + .../translations/zh_CN/virt/ne_overview.rst | 88 + .../translations/zh_CN/virt/paravirt_ops.rst | 41 + Documentation/translations/zh_TW/IRQ.txt | 41 + .../translations/zh_TW/admin-guide/README.rst | 351 +++ .../translations/zh_TW/admin-guide/bug-bisect.rst | 85 + .../translations/zh_TW/admin-guide/bug-hunting.rst | 344 +++ .../zh_TW/admin-guide/clearing-warn-once.rst | 16 + .../translations/zh_TW/admin-guide/cpu-load.rst | 112 + .../translations/zh_TW/admin-guide/index.rst | 135 + .../translations/zh_TW/admin-guide/init.rst | 58 + .../zh_TW/admin-guide/reporting-issues.rst | 1337 +++++++++ .../zh_TW/admin-guide/security-bugs.rst | 78 + .../zh_TW/admin-guide/tainted-kernels.rst | 161 ++ .../translations/zh_TW/admin-guide/unicode.rst | 174 ++ Documentation/translations/zh_TW/arm64/amu.rst | 104 + Documentation/translations/zh_TW/arm64/booting.txt | 251 ++ .../translations/zh_TW/arm64/elf_hwcaps.rst | 244 ++ .../translations/zh_TW/arm64/hugetlbpage.rst | 49 + Documentation/translations/zh_TW/arm64/index.rst | 23 + .../zh_TW/arm64/legacy_instructions.txt | 77 + Documentation/translations/zh_TW/arm64/memory.txt | 119 + Documentation/translations/zh_TW/arm64/perf.rst | 88 + .../translations/zh_TW/arm64/silicon-errata.txt | 79 + .../translations/zh_TW/arm64/tagged-pointers.txt | 57 + Documentation/translations/zh_TW/cpu-freq/core.rst | 108 + .../translations/zh_TW/cpu-freq/cpu-drivers.rst | 256 ++ .../translations/zh_TW/cpu-freq/cpufreq-stats.rst | 132 + .../translations/zh_TW/cpu-freq/index.rst | 47 + .../translations/zh_TW/disclaimer-zh_TW.rst | 11 + .../translations/zh_TW/filesystems/debugfs.rst | 224 ++ .../translations/zh_TW/filesystems/index.rst | 31 + .../translations/zh_TW/filesystems/sysfs.txt | 377 +++ .../translations/zh_TW/filesystems/tmpfs.rst | 148 + .../translations/zh_TW/filesystems/virtiofs.rst | 61 + Documentation/translations/zh_TW/gpio.txt | 651 +++++ Documentation/translations/zh_TW/index.rst | 177 ++ Documentation/translations/zh_TW/io_ordering.txt | 68 + .../translations/zh_TW/process/1.Intro.rst | 199 ++ .../translations/zh_TW/process/2.Process.rst | 369 +++ .../translations/zh_TW/process/3.Early-stage.rst | 172 ++ .../translations/zh_TW/process/4.Coding.rst | 297 ++ .../translations/zh_TW/process/5.Posting.rst | 250 ++ .../translations/zh_TW/process/6.Followthrough.rst | 156 ++ .../zh_TW/process/7.AdvancedTopics.rst | 137 + .../translations/zh_TW/process/8.Conclusion.rst | 73 + .../process/code-of-conduct-interpretation.rst | 112 + .../translations/zh_TW/process/code-of-conduct.rst | 76 + .../translations/zh_TW/process/coding-style.rst | 958 +++++++ .../zh_TW/process/development-process.rst | 30 + .../translations/zh_TW/process/email-clients.rst | 252 ++ .../zh_TW/process/embargoed-hardware-issues.rst | 232 ++ Documentation/translations/zh_TW/process/howto.rst | 499 ++++ Documentation/translations/zh_TW/process/index.rst | 66 + .../zh_TW/process/kernel-driver-statement.rst | 203 ++ .../zh_TW/process/kernel-enforcement-statement.rst | 155 ++ .../translations/zh_TW/process/license-rules.rst | 374 +++ .../translations/zh_TW/process/magic-number.rst | 77 + .../zh_TW/process/management-style.rst | 211 ++ .../zh_TW/process/programming-language.rst | 75 + .../zh_TW/process/stable-api-nonsense.rst | 159 ++ .../zh_TW/process/stable-kernel-rules.rst | 68 + .../zh_TW/process/submit-checklist.rst | 109 + .../zh_TW/process/submitting-patches.rst | 660 +++++ .../zh_TW/process/volatile-considered-harmful.rst | 110 + Documentation/translations/zh_TW/sparse.txt | 91 + 368 files changed, 72446 insertions(+) create mode 100644 Documentation/translations/index.rst create mode 100644 Documentation/translations/it_IT/admin-guide/README.rst create mode 100644 Documentation/translations/it_IT/admin-guide/kernel-parameters.rst create mode 100644 Documentation/translations/it_IT/admin-guide/security-bugs.rst create mode 100644 Documentation/translations/it_IT/core-api/index.rst create mode 100644 Documentation/translations/it_IT/core-api/memory-allocation.rst create mode 100644 Documentation/translations/it_IT/core-api/symbol-namespaces.rst create mode 100644 Documentation/translations/it_IT/devicetree/bindings/submitting-patches.rst create mode 100644 Documentation/translations/it_IT/disclaimer-ita.rst create mode 100644 Documentation/translations/it_IT/doc-guide/index.rst create mode 100644 Documentation/translations/it_IT/doc-guide/kernel-doc.rst create mode 100644 Documentation/translations/it_IT/doc-guide/parse-headers.rst create mode 100644 Documentation/translations/it_IT/doc-guide/sphinx.rst create mode 100644 Documentation/translations/it_IT/index.rst create mode 100644 Documentation/translations/it_IT/kernel-hacking/hacking.rst create mode 100644 Documentation/translations/it_IT/kernel-hacking/index.rst create mode 100644 Documentation/translations/it_IT/kernel-hacking/locking.rst create mode 100644 Documentation/translations/it_IT/maintainer/configure-git.rst create mode 100644 Documentation/translations/it_IT/networking/netdev-FAQ.rst create mode 100644 Documentation/translations/it_IT/process/1.Intro.rst create mode 100644 Documentation/translations/it_IT/process/2.Process.rst create mode 100644 Documentation/translations/it_IT/process/3.Early-stage.rst create mode 100644 Documentation/translations/it_IT/process/4.Coding.rst create mode 100644 Documentation/translations/it_IT/process/5.Posting.rst create mode 100644 Documentation/translations/it_IT/process/6.Followthrough.rst create mode 100644 Documentation/translations/it_IT/process/7.AdvancedTopics.rst create mode 100644 Documentation/translations/it_IT/process/8.Conclusion.rst create mode 100644 Documentation/translations/it_IT/process/adding-syscalls.rst create mode 100644 Documentation/translations/it_IT/process/applying-patches.rst create mode 100644 Documentation/translations/it_IT/process/changes.rst create mode 100644 Documentation/translations/it_IT/process/clang-format.rst create mode 100644 Documentation/translations/it_IT/process/code-of-conduct.rst create mode 100644 Documentation/translations/it_IT/process/coding-style.rst create mode 100644 Documentation/translations/it_IT/process/deprecated.rst create mode 100644 Documentation/translations/it_IT/process/development-process.rst create mode 100644 Documentation/translations/it_IT/process/email-clients.rst create mode 100644 Documentation/translations/it_IT/process/howto.rst create mode 100644 Documentation/translations/it_IT/process/index.rst create mode 100644 Documentation/translations/it_IT/process/kernel-docs.rst create mode 100644 Documentation/translations/it_IT/process/kernel-driver-statement.rst create mode 100644 Documentation/translations/it_IT/process/kernel-enforcement-statement.rst create mode 100644 Documentation/translations/it_IT/process/license-rules.rst create mode 100644 Documentation/translations/it_IT/process/magic-number.rst create mode 100644 Documentation/translations/it_IT/process/maintainer-handbooks.rst create mode 100644 Documentation/translations/it_IT/process/maintainer-pgp-guide.rst create mode 100644 Documentation/translations/it_IT/process/maintainer-tip.rst create mode 100644 Documentation/translations/it_IT/process/maintainers.rst create mode 100644 Documentation/translations/it_IT/process/management-style.rst create mode 100644 Documentation/translations/it_IT/process/programming-language.rst create mode 100644 Documentation/translations/it_IT/process/stable-api-nonsense.rst create mode 100644 Documentation/translations/it_IT/process/stable-kernel-rules.rst create mode 100644 Documentation/translations/it_IT/process/submit-checklist.rst create mode 100644 Documentation/translations/it_IT/process/submitting-patches.rst create mode 100644 Documentation/translations/it_IT/process/volatile-considered-harmful.rst create mode 100644 Documentation/translations/it_IT/riscv/patch-acceptance.rst create mode 100644 Documentation/translations/ja_JP/SubmitChecklist create mode 100644 Documentation/translations/ja_JP/SubmittingPatches create mode 100644 Documentation/translations/ja_JP/howto.rst create mode 100644 Documentation/translations/ja_JP/index.rst create mode 100644 Documentation/translations/ja_JP/stable_api_nonsense.txt create mode 100644 Documentation/translations/ja_JP/stable_kernel_rules.txt create mode 100644 Documentation/translations/ko_KR/howto.rst create mode 100644 Documentation/translations/ko_KR/index.rst create mode 100644 Documentation/translations/ko_KR/memory-barriers.txt create mode 100644 Documentation/translations/ko_KR/stable_api_nonsense.txt create mode 100644 Documentation/translations/zh_CN/PCI/acpi-info.rst create mode 100644 Documentation/translations/zh_CN/PCI/index.rst create mode 100644 Documentation/translations/zh_CN/PCI/msi-howto.rst create mode 100644 Documentation/translations/zh_CN/PCI/pci-iov-howto.rst create mode 100644 Documentation/translations/zh_CN/PCI/pci.rst create mode 100644 Documentation/translations/zh_CN/PCI/pciebus-howto.rst create mode 100644 Documentation/translations/zh_CN/PCI/sysfs-pci.rst create mode 100644 Documentation/translations/zh_CN/accounting/delay-accounting.rst create mode 100644 Documentation/translations/zh_CN/accounting/index.rst create mode 100644 Documentation/translations/zh_CN/accounting/psi.rst create mode 100644 Documentation/translations/zh_CN/accounting/taskstats.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/README.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/bootconfig.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/bug-bisect.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/bug-hunting.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/clearing-warn-once.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/cpu-load.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/cputopology.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/index.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/init.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/lockup-watchdogs.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/mm/damon/index.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/mm/damon/reclaim.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/mm/damon/start.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/mm/damon/usage.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/mm/index.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/mm/ksm.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/reporting-issues.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/reporting-regressions.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/security-bugs.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/sysrq.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/tainted-kernels.rst create mode 100644 Documentation/translations/zh_CN/admin-guide/unicode.rst create mode 100644 Documentation/translations/zh_CN/arch.rst create mode 100644 Documentation/translations/zh_CN/arm/Booting create mode 100644 Documentation/translations/zh_CN/arm/kernel_user_helpers.txt create mode 100644 Documentation/translations/zh_CN/arm64/amu.rst create mode 100644 Documentation/translations/zh_CN/arm64/booting.txt create mode 100644 Documentation/translations/zh_CN/arm64/elf_hwcaps.rst create mode 100644 Documentation/translations/zh_CN/arm64/hugetlbpage.rst create mode 100644 Documentation/translations/zh_CN/arm64/index.rst create mode 100644 Documentation/translations/zh_CN/arm64/legacy_instructions.txt create mode 100644 Documentation/translations/zh_CN/arm64/memory.txt create mode 100644 Documentation/translations/zh_CN/arm64/perf.rst create mode 100644 Documentation/translations/zh_CN/arm64/silicon-errata.txt create mode 100644 Documentation/translations/zh_CN/arm64/tagged-pointers.txt create mode 100644 Documentation/translations/zh_CN/core-api/assoc_array.rst create mode 100644 Documentation/translations/zh_CN/core-api/boot-time-mm.rst create mode 100644 Documentation/translations/zh_CN/core-api/cachetlb.rst create mode 100644 Documentation/translations/zh_CN/core-api/circular-buffers.rst create mode 100644 Documentation/translations/zh_CN/core-api/cpu_hotplug.rst create mode 100644 Documentation/translations/zh_CN/core-api/genalloc.rst create mode 100644 Documentation/translations/zh_CN/core-api/generic-radix-tree.rst create mode 100644 Documentation/translations/zh_CN/core-api/genericirq.rst create mode 100644 Documentation/translations/zh_CN/core-api/gfp_mask-from-fs-io.rst create mode 100644 Documentation/translations/zh_CN/core-api/idr.rst create mode 100644 Documentation/translations/zh_CN/core-api/index.rst create mode 100644 Documentation/translations/zh_CN/core-api/irq/concepts.rst create mode 100644 Documentation/translations/zh_CN/core-api/irq/index.rst create mode 100644 Documentation/translations/zh_CN/core-api/irq/irq-affinity.rst create mode 100644 Documentation/translations/zh_CN/core-api/irq/irq-domain.rst create mode 100644 Documentation/translations/zh_CN/core-api/irq/irqflags-tracing.rst create mode 100644 Documentation/translations/zh_CN/core-api/kernel-api.rst create mode 100644 Documentation/translations/zh_CN/core-api/kobject.rst create mode 100644 Documentation/translations/zh_CN/core-api/kref.rst create mode 100644 Documentation/translations/zh_CN/core-api/local_ops.rst create mode 100644 Documentation/translations/zh_CN/core-api/memory-allocation.rst create mode 100644 Documentation/translations/zh_CN/core-api/memory-hotplug.rst create mode 100644 Documentation/translations/zh_CN/core-api/mm-api.rst create mode 100644 Documentation/translations/zh_CN/core-api/packing.rst create mode 100644 Documentation/translations/zh_CN/core-api/padata.rst create mode 100644 Documentation/translations/zh_CN/core-api/printk-basics.rst create mode 100644 Documentation/translations/zh_CN/core-api/printk-formats.rst create mode 100644 Documentation/translations/zh_CN/core-api/protection-keys.rst create mode 100644 Documentation/translations/zh_CN/core-api/rbtree.rst create mode 100644 Documentation/translations/zh_CN/core-api/refcount-vs-atomic.rst create mode 100644 Documentation/translations/zh_CN/core-api/symbol-namespaces.rst create mode 100644 Documentation/translations/zh_CN/core-api/unaligned-memory-access.rst create mode 100644 Documentation/translations/zh_CN/core-api/watch_queue.rst create mode 100644 Documentation/translations/zh_CN/core-api/workqueue.rst create mode 100644 Documentation/translations/zh_CN/core-api/xarray.rst create mode 100644 Documentation/translations/zh_CN/cpu-freq/core.rst create mode 100644 Documentation/translations/zh_CN/cpu-freq/cpu-drivers.rst create mode 100644 Documentation/translations/zh_CN/cpu-freq/cpufreq-stats.rst create mode 100644 Documentation/translations/zh_CN/cpu-freq/index.rst create mode 100644 Documentation/translations/zh_CN/dev-tools/gcov.rst create mode 100644 Documentation/translations/zh_CN/dev-tools/gdb-kernel-debugging.rst create mode 100644 Documentation/translations/zh_CN/dev-tools/index.rst create mode 100644 Documentation/translations/zh_CN/dev-tools/kasan.rst create mode 100644 Documentation/translations/zh_CN/dev-tools/sparse.rst create mode 100644 Documentation/translations/zh_CN/dev-tools/testing-overview.rst create mode 100644 Documentation/translations/zh_CN/devicetree/changesets.rst create mode 100644 Documentation/translations/zh_CN/devicetree/dynamic-resolution-notes.rst create mode 100644 Documentation/translations/zh_CN/devicetree/index.rst create mode 100644 Documentation/translations/zh_CN/devicetree/kernel-api.rst create mode 100644 Documentation/translations/zh_CN/devicetree/of_unittest.rst create mode 100644 Documentation/translations/zh_CN/devicetree/overlay-notes.rst create mode 100644 Documentation/translations/zh_CN/devicetree/usage-model.rst create mode 100644 Documentation/translations/zh_CN/disclaimer-zh_CN.rst create mode 100644 Documentation/translations/zh_CN/doc-guide/contributing.rst create mode 100644 Documentation/translations/zh_CN/doc-guide/index.rst create mode 100644 Documentation/translations/zh_CN/doc-guide/kernel-doc.rst create mode 100644 Documentation/translations/zh_CN/doc-guide/maintainer-profile.rst create mode 100644 Documentation/translations/zh_CN/doc-guide/parse-headers.rst create mode 100644 Documentation/translations/zh_CN/doc-guide/sphinx.rst create mode 100644 Documentation/translations/zh_CN/driver-api/gpio/index.rst create mode 100644 Documentation/translations/zh_CN/driver-api/gpio/legacy.rst create mode 100644 Documentation/translations/zh_CN/driver-api/index.rst create mode 100644 Documentation/translations/zh_CN/driver-api/io_ordering.rst create mode 100644 Documentation/translations/zh_CN/filesystems/debugfs.rst create mode 100644 Documentation/translations/zh_CN/filesystems/index.rst create mode 100644 Documentation/translations/zh_CN/filesystems/sysfs.txt create mode 100644 Documentation/translations/zh_CN/filesystems/tmpfs.rst create mode 100644 Documentation/translations/zh_CN/filesystems/virtiofs.rst create mode 100644 Documentation/translations/zh_CN/iio/ep93xx_adc.rst create mode 100644 Documentation/translations/zh_CN/iio/iio_configfs.rst create mode 100644 Documentation/translations/zh_CN/iio/index.rst create mode 100644 Documentation/translations/zh_CN/index.rst create mode 100644 Documentation/translations/zh_CN/infiniband/core_locking.rst create mode 100644 Documentation/translations/zh_CN/infiniband/index.rst create mode 100644 Documentation/translations/zh_CN/infiniband/ipoib.rst create mode 100644 Documentation/translations/zh_CN/infiniband/opa_vnic.rst create mode 100644 Documentation/translations/zh_CN/infiniband/sysfs.rst create mode 100644 Documentation/translations/zh_CN/infiniband/tag_matching.rst create mode 100644 Documentation/translations/zh_CN/infiniband/user_mad.rst create mode 100644 Documentation/translations/zh_CN/infiniband/user_verbs.rst create mode 100644 Documentation/translations/zh_CN/kernel-hacking/hacking.rst create mode 100644 Documentation/translations/zh_CN/kernel-hacking/index.rst create mode 100644 Documentation/translations/zh_CN/locking/index.rst create mode 100644 Documentation/translations/zh_CN/locking/mutex-design.rst create mode 100644 Documentation/translations/zh_CN/locking/spinlocks.rst create mode 100644 Documentation/translations/zh_CN/loongarch/booting.rst create mode 100644 Documentation/translations/zh_CN/loongarch/features.rst create mode 100644 Documentation/translations/zh_CN/loongarch/index.rst create mode 100644 Documentation/translations/zh_CN/loongarch/introduction.rst create mode 100644 Documentation/translations/zh_CN/loongarch/irq-chip-model.rst create mode 100644 Documentation/translations/zh_CN/maintainer/configure-git.rst create mode 100644 Documentation/translations/zh_CN/maintainer/index.rst create mode 100644 Documentation/translations/zh_CN/maintainer/maintainer-entry-profile.rst create mode 100644 Documentation/translations/zh_CN/maintainer/modifying-patches.rst create mode 100644 Documentation/translations/zh_CN/maintainer/pull-requests.rst create mode 100644 Documentation/translations/zh_CN/maintainer/rebasing-and-merging.rst create mode 100644 Documentation/translations/zh_CN/mips/booting.rst create mode 100644 Documentation/translations/zh_CN/mips/features.rst create mode 100644 Documentation/translations/zh_CN/mips/index.rst create mode 100644 Documentation/translations/zh_CN/mips/ingenic-tcu.rst create mode 100644 Documentation/translations/zh_CN/mm/active_mm.rst create mode 100644 Documentation/translations/zh_CN/mm/balance.rst create mode 100644 Documentation/translations/zh_CN/mm/damon/api.rst create mode 100644 Documentation/translations/zh_CN/mm/damon/design.rst create mode 100644 Documentation/translations/zh_CN/mm/damon/faq.rst create mode 100644 Documentation/translations/zh_CN/mm/damon/index.rst create mode 100644 Documentation/translations/zh_CN/mm/free_page_reporting.rst create mode 100644 Documentation/translations/zh_CN/mm/frontswap.rst create mode 100644 Documentation/translations/zh_CN/mm/highmem.rst create mode 100644 Documentation/translations/zh_CN/mm/hmm.rst create mode 100644 Documentation/translations/zh_CN/mm/hugetlbfs_reserv.rst create mode 100644 Documentation/translations/zh_CN/mm/hwpoison.rst create mode 100644 Documentation/translations/zh_CN/mm/index.rst create mode 100644 Documentation/translations/zh_CN/mm/ksm.rst create mode 100644 Documentation/translations/zh_CN/mm/memory-model.rst create mode 100644 Documentation/translations/zh_CN/mm/mmu_notifier.rst create mode 100644 Documentation/translations/zh_CN/mm/numa.rst create mode 100644 Documentation/translations/zh_CN/mm/overcommit-accounting.rst create mode 100644 Documentation/translations/zh_CN/mm/page_frags.rst create mode 100644 Documentation/translations/zh_CN/mm/page_migration.rst create mode 100644 Documentation/translations/zh_CN/mm/page_owner.rst create mode 100644 Documentation/translations/zh_CN/mm/page_table_check.rst create mode 100644 Documentation/translations/zh_CN/mm/remap_file_pages.rst create mode 100644 Documentation/translations/zh_CN/mm/split_page_table_lock.rst create mode 100644 Documentation/translations/zh_CN/mm/vmalloced-kernel-stacks.rst create mode 100644 Documentation/translations/zh_CN/mm/z3fold.rst create mode 100644 Documentation/translations/zh_CN/mm/zsmalloc.rst create mode 100644 Documentation/translations/zh_CN/openrisc/index.rst create mode 100644 Documentation/translations/zh_CN/openrisc/openrisc_port.rst create mode 100644 Documentation/translations/zh_CN/openrisc/todo.rst create mode 100644 Documentation/translations/zh_CN/parisc/debugging.rst create mode 100644 Documentation/translations/zh_CN/parisc/index.rst create mode 100644 Documentation/translations/zh_CN/parisc/registers.rst create mode 100644 Documentation/translations/zh_CN/peci/index.rst create mode 100644 Documentation/translations/zh_CN/peci/peci.rst create mode 100644 Documentation/translations/zh_CN/power/energy-model.rst create mode 100644 Documentation/translations/zh_CN/power/index.rst create mode 100644 Documentation/translations/zh_CN/power/opp.rst create mode 100644 Documentation/translations/zh_CN/process/1.Intro.rst create mode 100644 Documentation/translations/zh_CN/process/2.Process.rst create mode 100644 Documentation/translations/zh_CN/process/3.Early-stage.rst create mode 100644 Documentation/translations/zh_CN/process/4.Coding.rst create mode 100644 Documentation/translations/zh_CN/process/5.Posting.rst create mode 100644 Documentation/translations/zh_CN/process/6.Followthrough.rst create mode 100644 Documentation/translations/zh_CN/process/7.AdvancedTopics.rst create mode 100644 Documentation/translations/zh_CN/process/8.Conclusion.rst create mode 100644 Documentation/translations/zh_CN/process/code-of-conduct-interpretation.rst create mode 100644 Documentation/translations/zh_CN/process/code-of-conduct.rst create mode 100644 Documentation/translations/zh_CN/process/coding-style.rst create mode 100644 Documentation/translations/zh_CN/process/development-process.rst create mode 100644 Documentation/translations/zh_CN/process/email-clients.rst create mode 100644 Documentation/translations/zh_CN/process/embargoed-hardware-issues.rst create mode 100644 Documentation/translations/zh_CN/process/howto.rst create mode 100644 Documentation/translations/zh_CN/process/index.rst create mode 100644 Documentation/translations/zh_CN/process/kernel-driver-statement.rst create mode 100644 Documentation/translations/zh_CN/process/kernel-enforcement-statement.rst create mode 100644 Documentation/translations/zh_CN/process/license-rules.rst create mode 100644 Documentation/translations/zh_CN/process/magic-number.rst create mode 100644 Documentation/translations/zh_CN/process/management-style.rst create mode 100644 Documentation/translations/zh_CN/process/programming-language.rst create mode 100644 Documentation/translations/zh_CN/process/stable-api-nonsense.rst create mode 100644 Documentation/translations/zh_CN/process/stable-kernel-rules.rst create mode 100644 Documentation/translations/zh_CN/process/submit-checklist.rst create mode 100644 Documentation/translations/zh_CN/process/submitting-patches.rst create mode 100644 Documentation/translations/zh_CN/process/volatile-considered-harmful.rst create mode 100644 Documentation/translations/zh_CN/riscv/boot-image-header.rst create mode 100644 Documentation/translations/zh_CN/riscv/index.rst create mode 100644 Documentation/translations/zh_CN/riscv/patch-acceptance.rst create mode 100644 Documentation/translations/zh_CN/riscv/vm-layout.rst create mode 100644 Documentation/translations/zh_CN/scheduler/completion.rst create mode 100644 Documentation/translations/zh_CN/scheduler/index.rst create mode 100644 Documentation/translations/zh_CN/scheduler/sched-arch.rst create mode 100644 Documentation/translations/zh_CN/scheduler/sched-bwc.rst create mode 100644 Documentation/translations/zh_CN/scheduler/sched-capacity.rst create mode 100644 Documentation/translations/zh_CN/scheduler/sched-debug.rst create mode 100644 Documentation/translations/zh_CN/scheduler/sched-design-CFS.rst create mode 100644 Documentation/translations/zh_CN/scheduler/sched-domains.rst create mode 100644 Documentation/translations/zh_CN/scheduler/sched-energy.rst create mode 100644 Documentation/translations/zh_CN/scheduler/sched-nice-design.rst create mode 100644 Documentation/translations/zh_CN/scheduler/sched-stats.rst create mode 100644 Documentation/translations/zh_CN/scheduler/schedutil.rst create mode 100644 Documentation/translations/zh_CN/sound/hd-audio/controls.rst create mode 100644 Documentation/translations/zh_CN/sound/hd-audio/index.rst create mode 100644 Documentation/translations/zh_CN/sound/index.rst create mode 100644 Documentation/translations/zh_CN/video4linux/omap3isp.txt create mode 100644 Documentation/translations/zh_CN/video4linux/v4l2-framework.txt create mode 100644 Documentation/translations/zh_CN/virt/acrn/cpuid.rst create mode 100644 Documentation/translations/zh_CN/virt/acrn/index.rst create mode 100644 Documentation/translations/zh_CN/virt/acrn/introduction.rst create mode 100644 Documentation/translations/zh_CN/virt/acrn/io-request.rst create mode 100644 Documentation/translations/zh_CN/virt/guest-halt-polling.rst create mode 100644 Documentation/translations/zh_CN/virt/index.rst create mode 100644 Documentation/translations/zh_CN/virt/ne_overview.rst create mode 100644 Documentation/translations/zh_CN/virt/paravirt_ops.rst create mode 100644 Documentation/translations/zh_TW/IRQ.txt create mode 100644 Documentation/translations/zh_TW/admin-guide/README.rst create mode 100644 Documentation/translations/zh_TW/admin-guide/bug-bisect.rst create mode 100644 Documentation/translations/zh_TW/admin-guide/bug-hunting.rst create mode 100644 Documentation/translations/zh_TW/admin-guide/clearing-warn-once.rst create mode 100644 Documentation/translations/zh_TW/admin-guide/cpu-load.rst create mode 100644 Documentation/translations/zh_TW/admin-guide/index.rst create mode 100644 Documentation/translations/zh_TW/admin-guide/init.rst create mode 100644 Documentation/translations/zh_TW/admin-guide/reporting-issues.rst create mode 100644 Documentation/translations/zh_TW/admin-guide/security-bugs.rst create mode 100644 Documentation/translations/zh_TW/admin-guide/tainted-kernels.rst create mode 100644 Documentation/translations/zh_TW/admin-guide/unicode.rst create mode 100644 Documentation/translations/zh_TW/arm64/amu.rst create mode 100644 Documentation/translations/zh_TW/arm64/booting.txt create mode 100644 Documentation/translations/zh_TW/arm64/elf_hwcaps.rst create mode 100644 Documentation/translations/zh_TW/arm64/hugetlbpage.rst create mode 100644 Documentation/translations/zh_TW/arm64/index.rst create mode 100644 Documentation/translations/zh_TW/arm64/legacy_instructions.txt create mode 100644 Documentation/translations/zh_TW/arm64/memory.txt create mode 100644 Documentation/translations/zh_TW/arm64/perf.rst create mode 100644 Documentation/translations/zh_TW/arm64/silicon-errata.txt create mode 100644 Documentation/translations/zh_TW/arm64/tagged-pointers.txt create mode 100644 Documentation/translations/zh_TW/cpu-freq/core.rst create mode 100644 Documentation/translations/zh_TW/cpu-freq/cpu-drivers.rst create mode 100644 Documentation/translations/zh_TW/cpu-freq/cpufreq-stats.rst create mode 100644 Documentation/translations/zh_TW/cpu-freq/index.rst create mode 100644 Documentation/translations/zh_TW/disclaimer-zh_TW.rst create mode 100644 Documentation/translations/zh_TW/filesystems/debugfs.rst create mode 100644 Documentation/translations/zh_TW/filesystems/index.rst create mode 100644 Documentation/translations/zh_TW/filesystems/sysfs.txt create mode 100644 Documentation/translations/zh_TW/filesystems/tmpfs.rst create mode 100644 Documentation/translations/zh_TW/filesystems/virtiofs.rst create mode 100644 Documentation/translations/zh_TW/gpio.txt create mode 100644 Documentation/translations/zh_TW/index.rst create mode 100644 Documentation/translations/zh_TW/io_ordering.txt create mode 100644 Documentation/translations/zh_TW/process/1.Intro.rst create mode 100644 Documentation/translations/zh_TW/process/2.Process.rst create mode 100644 Documentation/translations/zh_TW/process/3.Early-stage.rst create mode 100644 Documentation/translations/zh_TW/process/4.Coding.rst create mode 100644 Documentation/translations/zh_TW/process/5.Posting.rst create mode 100644 Documentation/translations/zh_TW/process/6.Followthrough.rst create mode 100644 Documentation/translations/zh_TW/process/7.AdvancedTopics.rst create mode 100644 Documentation/translations/zh_TW/process/8.Conclusion.rst create mode 100644 Documentation/translations/zh_TW/process/code-of-conduct-interpretation.rst create mode 100644 Documentation/translations/zh_TW/process/code-of-conduct.rst create mode 100644 Documentation/translations/zh_TW/process/coding-style.rst create mode 100644 Documentation/translations/zh_TW/process/development-process.rst create mode 100644 Documentation/translations/zh_TW/process/email-clients.rst create mode 100644 Documentation/translations/zh_TW/process/embargoed-hardware-issues.rst create mode 100644 Documentation/translations/zh_TW/process/howto.rst create mode 100644 Documentation/translations/zh_TW/process/index.rst create mode 100644 Documentation/translations/zh_TW/process/kernel-driver-statement.rst create mode 100644 Documentation/translations/zh_TW/process/kernel-enforcement-statement.rst create mode 100644 Documentation/translations/zh_TW/process/license-rules.rst create mode 100644 Documentation/translations/zh_TW/process/magic-number.rst create mode 100644 Documentation/translations/zh_TW/process/management-style.rst create mode 100644 Documentation/translations/zh_TW/process/programming-language.rst create mode 100644 Documentation/translations/zh_TW/process/stable-api-nonsense.rst create mode 100644 Documentation/translations/zh_TW/process/stable-kernel-rules.rst create mode 100644 Documentation/translations/zh_TW/process/submit-checklist.rst create mode 100644 Documentation/translations/zh_TW/process/submitting-patches.rst create mode 100644 Documentation/translations/zh_TW/process/volatile-considered-harmful.rst create mode 100644 Documentation/translations/zh_TW/sparse.txt (limited to 'Documentation/translations') diff --git a/Documentation/translations/index.rst b/Documentation/translations/index.rst new file mode 100644 index 000000000..1175a47d0 --- /dev/null +++ b/Documentation/translations/index.rst @@ -0,0 +1,58 @@ +.. _translations: + +============ +Translations +============ + +.. toctree:: + :maxdepth: 1 + + zh_CN/index + zh_TW/index + it_IT/index + ko_KR/index + ja_JP/index + + +.. _translations_disclaimer: + +Disclaimer +---------- + +.. raw:: latex + + \kerneldocCJKoff + +Translation's purpose is to ease reading and understanding in languages other +than English. Its aim is to help people who do not understand English or have +doubts about its interpretation. Additionally, some people prefer to read +documentation in their native language, but please bear in mind that the +*only* official documentation is the English one: :ref:`linux_doc`. + +It is very unlikely that an update to :ref:`linux_doc` will be propagated +immediately to all translations. Translations' maintainers - and +contributors - follow the evolution of the official documentation and they +maintain translations aligned as much as they can. For this reason there is +no guarantee that a translation is up to date. If what you read in a +translation does not sound right compared to what you read in the code, please +inform the translation maintainer and - if you can - check also the English +documentation. + +A translation is not a fork of the official documentation, therefore +translations' users should not find information that differs from the official +English documentation. Any content addition, removal or update, must be +applied to the English documents first. Afterwards and when possible, the +same change should be applied to translations. Translations' maintainers +accept only contributions that are merely translation related (e.g. new +translations, updates, fixes). + +Translations try to be as accurate as possible but it is not possible to map +one language directly to all other languages. Each language has its own +grammar and culture, so the translation of an English statement may need to be +adapted to fit a different language. For this reason, when viewing +translations, you may find slight differences that carry the same message but +in a different form. + +If you need to communicate with the Linux community but you do not feel +comfortable writing in English, you can ask the translation's maintainers +for help. diff --git a/Documentation/translations/it_IT/admin-guide/README.rst b/Documentation/translations/it_IT/admin-guide/README.rst new file mode 100644 index 000000000..b37166817 --- /dev/null +++ b/Documentation/translations/it_IT/admin-guide/README.rst @@ -0,0 +1,12 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/admin-guide/README.rst ` + +.. _it_readme: + +Rilascio del kernel Linux 5.x +=================================================== + +.. warning:: + + TODO ancora da tradurre diff --git a/Documentation/translations/it_IT/admin-guide/kernel-parameters.rst b/Documentation/translations/it_IT/admin-guide/kernel-parameters.rst new file mode 100644 index 000000000..0e36d82a9 --- /dev/null +++ b/Documentation/translations/it_IT/admin-guide/kernel-parameters.rst @@ -0,0 +1,12 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/admin-guide/kernel-parameters.rst ` + +.. _it_kernelparameters: + +I parametri da linea di comando del kernel +========================================== + +.. warning:: + + TODO ancora da tradurre diff --git a/Documentation/translations/it_IT/admin-guide/security-bugs.rst b/Documentation/translations/it_IT/admin-guide/security-bugs.rst new file mode 100644 index 000000000..18a5822c7 --- /dev/null +++ b/Documentation/translations/it_IT/admin-guide/security-bugs.rst @@ -0,0 +1,12 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/admin-guide/security-bugs.rst ` + +.. _it_securitybugs: + +Bachi di sicurezza +================== + +.. warning:: + + TODO ancora da tradurre diff --git a/Documentation/translations/it_IT/core-api/index.rst b/Documentation/translations/it_IT/core-api/index.rst new file mode 100644 index 000000000..cc4c4328a --- /dev/null +++ b/Documentation/translations/it_IT/core-api/index.rst @@ -0,0 +1,18 @@ +=============================== +Documentazione dell'API di base +=============================== + +Utilità di base +=============== + +.. toctree:: + :maxdepth: 1 + + symbol-namespaces + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/translations/it_IT/core-api/memory-allocation.rst b/Documentation/translations/it_IT/core-api/memory-allocation.rst new file mode 100644 index 000000000..11d5148f8 --- /dev/null +++ b/Documentation/translations/it_IT/core-api/memory-allocation.rst @@ -0,0 +1,13 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/core-api/memory-allocation.rst ` + +.. _it_memory_allocation: + +================================ +Guida all'allocazione di memoria +================================ + +.. warning:: + + TODO ancora da tradurre diff --git a/Documentation/translations/it_IT/core-api/symbol-namespaces.rst b/Documentation/translations/it_IT/core-api/symbol-namespaces.rst new file mode 100644 index 000000000..0f6898860 --- /dev/null +++ b/Documentation/translations/it_IT/core-api/symbol-namespaces.rst @@ -0,0 +1,166 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :doc:`../../../core-api/symbol-namespaces` +:Translator: Federico Vaga + +=========================== +Spazio dei nomi dei simboli +=========================== + +Questo documento descrive come usare lo spazio dei nomi dei simboli +per strutturare quello che viene esportato internamente al kernel +grazie alle macro della famiglia EXPORT_SYMBOL(). + +1. Introduzione +=============== + +Lo spazio dei nomi dei simboli è stato introdotto come mezzo per strutturare +l'API esposta internamente al kernel. Permette ai manutentori di un +sottosistema di organizzare i simboli esportati in diversi spazi di +nomi. Questo meccanismo è utile per la documentazione (pensate ad +esempio allo spazio dei nomi SUBSYSTEM_DEBUG) così come per limitare +la disponibilità di un gruppo di simboli in altre parti del kernel. Ad +oggi, i moduli che usano simboli esportati da uno spazio di nomi +devono prima importare detto spazio. Altrimenti il kernel, a seconda +della configurazione, potrebbe rifiutare di caricare il modulo o +avvisare l'utente di un'importazione mancante. + +2. Come definire uno spazio dei nomi dei simboli +================================================ + +I simboli possono essere esportati in spazi dei nomi usando diversi +meccanismi. Tutti questi meccanismi cambiano il modo in cui +EXPORT_SYMBOL e simili vengono guidati verso la creazione di voci in ksymtab. + +2.1 Usare le macro EXPORT_SYMBOL +================================ + +In aggiunta alle macro EXPORT_SYMBOL() e EXPORT_SYMBOL_GPL(), che permettono +di esportare simboli del kernel nella rispettiva tabella, ci sono +varianti che permettono di esportare simboli all'interno di uno spazio dei +nomi: EXPORT_SYMBOL_NS() ed EXPORT_SYMBOL_NS_GPL(). Queste macro richiedono un +argomento aggiuntivo: lo spazio dei nomi. +Tenete presente che per via dell'espansione delle macro questo argomento deve +essere un simbolo di preprocessore. Per esempio per esportare il +simbolo ``usb_stor_suspend`` nello spazio dei nomi ``USB_STORAGE`` usate:: + + EXPORT_SYMBOL_NS(usb_stor_suspend, USB_STORAGE); + +Di conseguenza, nella tabella dei simboli del kernel ci sarà una voce +rappresentata dalla struttura ``kernel_symbol`` che avrà il campo +``namespace`` (spazio dei nomi) impostato. Un simbolo esportato senza uno spazio +dei nomi avrà questo campo impostato a ``NULL``. Non esiste uno spazio dei nomi +di base. Il programma ``modpost`` e il codice in kernel/module/main.c usano lo +spazio dei nomi, rispettivamente, durante la compilazione e durante il +caricamento di un modulo. + +2.2 Usare il simbolo di preprocessore DEFAULT_SYMBOL_NAMESPACE +============================================================== + +Definire lo spazio dei nomi per tutti i simboli di un sottosistema può essere +logorante e di difficile manutenzione. Perciò è stato fornito un simbolo +di preprocessore di base (DEFAULT_SYMBOL_NAMESPACE), che, se impostato, +diventa lo spazio dei simboli di base per tutti gli usi di EXPORT_SYMBOL() +ed EXPORT_SYMBOL_GPL() che non specificano esplicitamente uno spazio dei nomi. + +Ci sono molti modi per specificare questo simbolo di preprocessore e il loro +uso dipende dalle preferenze del manutentore di un sottosistema. La prima +possibilità è quella di definire il simbolo nel ``Makefile`` del sottosistema. +Per esempio per esportare tutti i simboli definiti in usb-common nello spazio +dei nomi USB_COMMON, si può aggiungere la seguente linea in +drivers/usb/common/Makefile:: + + ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON + +Questo cambierà tutte le macro EXPORT_SYMBOL() ed EXPORT_SYMBOL_GPL(). Invece, +un simbolo esportato con EXPORT_SYMBOL_NS() non verrà cambiato e il simbolo +verrà esportato nello spazio dei nomi indicato. + +Una seconda possibilità è quella di definire il simbolo di preprocessore +direttamente nei file da compilare. L'esempio precedente diventerebbe:: + + #undef DEFAULT_SYMBOL_NAMESPACE + #define DEFAULT_SYMBOL_NAMESPACE USB_COMMON + +Questo va messo prima di un qualsiasi uso di EXPORT_SYMBOL. + +3. Come usare i simboli esportati attraverso uno spazio dei nomi +================================================================ + +Per usare i simboli esportati da uno spazio dei nomi, i moduli del +kernel devono esplicitamente importare il relativo spazio dei nomi; altrimenti +il kernel potrebbe rifiutarsi di caricare il modulo. Il codice del +modulo deve usare la macro MODULE_IMPORT_NS per importare lo spazio +dei nomi che contiene i simboli desiderati. Per esempio un modulo che +usa il simbolo usb_stor_suspend deve importare lo spazio dei nomi +USB_STORAGE usando la seguente dichiarazione:: + + MODULE_IMPORT_NS(USB_STORAGE); + +Questo creerà un'etichetta ``modinfo`` per ogni spazio dei nomi +importato. Un risvolto di questo fatto è che gli spazi dei +nomi importati da un modulo possono essere ispezionati tramite +modinfo:: + + $ modinfo drivers/usb/storage/ums-karma.ko + [...] + import_ns: USB_STORAGE + [...] + + +Si consiglia di posizionare la dichiarazione MODULE_IMPORT_NS() vicino +ai metadati del modulo come MODULE_AUTHOR() o MODULE_LICENSE(). Fate +riferimento alla sezione 5. per creare automaticamente le importazioni +mancanti. + +4. Caricare moduli che usano simboli provenienti da spazi dei nomi +================================================================== + +Quando un modulo viene caricato (per esempio usando ``insmod``), il kernel +verificherà la disponibilità di ogni simbolo usato e se lo spazio dei nomi +che potrebbe contenerli è stato importato. Il comportamento di base del kernel +è di rifiutarsi di caricare quei moduli che non importano tutti gli spazi dei +nomi necessari. L'errore verrà annotato e il caricamento fallirà con l'errore +EINVAL. Per caricare i moduli che non soddisfano questo requisito esiste +un'opzione di configurazione: impostare +MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS=y caricherà i moduli comunque ma +emetterà un avviso. + +5. Creare automaticamente la dichiarazione MODULE_IMPORT_NS +=========================================================== + +La mancanza di un'importazione può essere individuata facilmente al momento +della compilazione. Infatti, modpost emetterà un avviso se il modulo usa +un simbolo da uno spazio dei nomi che non è stato importato. +La dichiarazione MODULE_IMPORT_NS() viene solitamente aggiunta in un posto +ben definito (assieme agli altri metadati del modulo). Per facilitare +la vita di chi scrive moduli (e i manutentori di sottosistemi), esistono uno +script e un target make per correggere le importazioni mancanti. Questo può +essere fatto con:: + + $ make nsdeps + +Lo scenario tipico di chi scrive un modulo potrebbe essere:: + + - scrivere codice che dipende da un simbolo appartenente ad uno spazio + dei nomi non importato + - eseguire ``make`` + - aver notato un avviso da modpost che parla di un'importazione + mancante + - eseguire ``make nsdeps`` per aggiungere import nel posto giusto + +Per i manutentori di sottosistemi che vogliono aggiungere uno spazio dei nomi, +l'approccio è simile. Di nuovo, eseguendo ``make nsdeps`` aggiungerà le +importazioni mancanti nei moduli inclusi nel kernel:: + + - spostare o aggiungere simboli ad uno spazio dei nomi (per esempio + usando EXPORT_SYMBOL_NS()) + - eseguire ``make`` (preferibilmente con allmodconfig per coprire tutti + i moduli del kernel) + - aver notato un avviso da modpost che parla di un'importazione + mancante + - eseguire ``make nsdeps`` per aggiungere import nel posto giusto + +Potete anche eseguire nsdeps per moduli esterni. Solitamente si usa così:: + + $ make -C M=$PWD nsdeps diff --git a/Documentation/translations/it_IT/devicetree/bindings/submitting-patches.rst b/Documentation/translations/it_IT/devicetree/bindings/submitting-patches.rst new file mode 100644 index 000000000..b473cd219 --- /dev/null +++ b/Documentation/translations/it_IT/devicetree/bindings/submitting-patches.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. include:: ../../disclaimer-ita.rst + +:Original: Documentation/devicetree/bindings/submitting-patches.rst + +================================================ +Sottomettere patch per devicetree (DT) *binding* +================================================ + +.. note:: to be translated diff --git a/Documentation/translations/it_IT/disclaimer-ita.rst b/Documentation/translations/it_IT/disclaimer-ita.rst new file mode 100644 index 000000000..bfe8a384b --- /dev/null +++ b/Documentation/translations/it_IT/disclaimer-ita.rst @@ -0,0 +1,6 @@ +:orphan: + +.. warning:: + In caso di dubbi sulla correttezza del contenuto di questa traduzione, + l'unico riferimento valido è la documentazione ufficiale in inglese. + Per maggiori informazioni consultate le :ref:`avvertenze `. diff --git a/Documentation/translations/it_IT/doc-guide/index.rst b/Documentation/translations/it_IT/doc-guide/index.rst new file mode 100644 index 000000000..9fffff626 --- /dev/null +++ b/Documentation/translations/it_IT/doc-guide/index.rst @@ -0,0 +1,24 @@ +.. include:: ../disclaimer-ita.rst + +.. note:: Per leggere la documentazione originale in inglese: + :ref:`Documentation/doc-guide/index.rst ` + +.. _it_doc_guide: + +========================================== +Come scrivere la documentazione del kernel +========================================== + +.. toctree:: + :maxdepth: 1 + + sphinx + kernel-doc + parse-headers + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/translations/it_IT/doc-guide/kernel-doc.rst b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst new file mode 100644 index 000000000..78082281a --- /dev/null +++ b/Documentation/translations/it_IT/doc-guide/kernel-doc.rst @@ -0,0 +1,561 @@ +.. include:: ../disclaimer-ita.rst + +.. note:: Per leggere la documentazione originale in inglese: + :ref:`Documentation/doc-guide/index.rst ` + +.. _it_kernel_doc: + +================================= +Scrivere i commenti in kernel-doc +================================= + +Nei file sorgenti del kernel Linux potrete trovare commenti di documentazione +strutturanti secondo il formato kernel-doc. Essi possono descrivere funzioni, +tipi di dati, e l'architettura del codice. + +.. note:: Il formato kernel-doc può sembrare simile a gtk-doc o Doxygen ma + in realtà è molto differente per ragioni storiche. I sorgenti del kernel + contengono decine di migliaia di commenti kernel-doc. Siete pregati + d'attenervi allo stile qui descritto. + +La struttura kernel-doc è estratta a partire dai commenti; da questi viene +generato il `dominio Sphinx per il C`_ con un'adeguata descrizione per le +funzioni ed i tipi di dato con i loro relativi collegamenti. Le descrizioni +vengono filtrare per cercare i riferimenti ed i marcatori. + +Vedere di seguito per maggiori dettagli. + +.. _`dominio Sphinx per il C`: http://www.sphinx-doc.org/en/stable/domains.html + +Tutte le funzioni esportate verso i moduli esterni utilizzando +``EXPORT_SYMBOL`` o ``EXPORT_SYMBOL_GPL`` dovrebbero avere un commento +kernel-doc. Quando l'intenzione è di utilizzarle nei moduli, anche le funzioni +e le strutture dati nei file d'intestazione dovrebbero avere dei commenti +kernel-doc. + +È considerata una buona pratica quella di fornire una documentazione formattata +secondo kernel-doc per le funzioni che sono visibili da altri file del kernel +(ovvero, che non siano dichiarate utilizzando ``static``). Raccomandiamo, +inoltre, di fornire una documentazione kernel-doc anche per procedure private +(ovvero, dichiarate "static") al fine di fornire una struttura più coerente +dei sorgenti. Quest'ultima raccomandazione ha una priorità più bassa ed è a +discrezione dal manutentore (MAINTAINER) del file sorgente. + + + +Sicuramente la documentazione formattata con kernel-doc è necessaria per +le funzioni che sono esportate verso i moduli esterni utilizzando +``EXPORT_SYMBOL`` o ``EXPORT_SYMBOL_GPL``. + +Cerchiamo anche di fornire una documentazione formattata secondo kernel-doc +per le funzioni che sono visibili da altri file del kernel (ovvero, che non +siano dichiarate utilizzando "static") + +Raccomandiamo, inoltre, di fornire una documentazione formattata con kernel-doc +anche per procedure private (ovvero, dichiarate "static") al fine di fornire +una struttura più coerente dei sorgenti. Questa raccomandazione ha una priorità +più bassa ed è a discrezione dal manutentore (MAINTAINER) del file sorgente. + +Le strutture dati visibili nei file di intestazione dovrebbero essere anch'esse +documentate utilizzando commenti formattati con kernel-doc. + +Come formattare i commenti kernel-doc +------------------------------------- + +I commenti kernel-doc iniziano con il marcatore ``/**``. Il programma +``kernel-doc`` estrarrà i commenti marchiati in questo modo. Il resto +del commento è formattato come un normale commento multilinea, ovvero +con un asterisco all'inizio d'ogni riga e che si conclude con ``*/`` +su una riga separata. + +I commenti kernel-doc di funzioni e tipi dovrebbero essere posizionati +appena sopra la funzione od il tipo che descrivono. Questo allo scopo di +aumentare la probabilità che chi cambia il codice si ricordi di aggiornare +anche la documentazione. I commenti kernel-doc di tipo più generale possono +essere posizionati ovunque nel file. + +Al fine di verificare che i commenti siano formattati correttamente, potete +eseguire il programma ``kernel-doc`` con un livello di verbosità alto e senza +che questo produca alcuna documentazione. Per esempio:: + + scripts/kernel-doc -v -none drivers/foo/bar.c + +Il formato della documentazione è verificato della procedura di generazione +del kernel quando viene richiesto di effettuare dei controlli extra con GCC:: + + make W=n + +Documentare le funzioni +------------------------ + +Generalmente il formato di un commento kernel-doc per funzioni e +macro simil-funzioni è il seguente:: + + /** + * function_name() - Brief description of function. + * @arg1: Describe the first argument. + * @arg2: Describe the second argument. + * One can provide multiple line descriptions + * for arguments. + * + * A longer description, with more discussion of the function function_name() + * that might be useful to those using or modifying it. Begins with an + * empty comment line, and may include additional embedded empty + * comment lines. + * + * The longer description may have multiple paragraphs. + * + * Context: Describes whether the function can sleep, what locks it takes, + * releases, or expects to be held. It can extend over multiple + * lines. + * Return: Describe the return value of function_name. + * + * The return value description can also have multiple paragraphs, and should + * be placed at the end of the comment block. + */ + +La descrizione introduttiva (*brief description*) che segue il nome della +funzione può continuare su righe successive e termina con la descrizione di +un argomento, una linea di commento vuota, oppure la fine del commento. + +Parametri delle funzioni +~~~~~~~~~~~~~~~~~~~~~~~~ + +Ogni argomento di una funzione dovrebbe essere descritto in ordine, subito +dopo la descrizione introduttiva. Non lasciare righe vuote né fra la +descrizione introduttiva e quella degli argomenti, né fra gli argomenti. + +Ogni ``@argument:`` può estendersi su più righe. + +.. note:: + + Se la descrizione di ``@argument:`` si estende su più righe, + la continuazione dovrebbe iniziare alla stessa colonna della riga + precedente:: + + * @argument: some long description + * that continues on next lines + + or:: + + * @argument: + * some long description + * that continues on next lines + +Se una funzione ha un numero variabile di argomento, la sua descrizione +dovrebbe essere scritta con la notazione kernel-doc:: + + * @...: description + +Contesto delle funzioni +~~~~~~~~~~~~~~~~~~~~~~~ + +Il contesto in cui le funzioni vengono chiamate viene descritto in una +sezione chiamata ``Context``. Questo dovrebbe informare sulla possibilità +che una funzione dorma (*sleep*) o che possa essere chiamata in un contesto +d'interruzione, così come i *lock* che prende, rilascia e che si aspetta che +vengano presi dal chiamante. + +Esempi:: + + * Context: Any context. + * Context: Any context. Takes and releases the RCU lock. + * Context: Any context. Expects to be held by caller. + * Context: Process context. May sleep if @gfp flags permit. + * Context: Process context. Takes and releases . + * Context: Softirq or process context. Takes and releases , BH-safe. + * Context: Interrupt context. + +Valore di ritorno +~~~~~~~~~~~~~~~~~ + +Il valore di ritorno, se c'è, viene descritto in una sezione dedicata di nome +``Return``. + +.. note:: + + #) La descrizione multiriga non riconosce il termine d'una riga, per cui + se provate a formattare bene il vostro testo come nel seguente esempio:: + + * Return: + * 0 - OK + * -EINVAL - invalid argument + * -ENOMEM - out of memory + + le righe verranno unite e il risultato sarà:: + + Return: 0 - OK -EINVAL - invalid argument -ENOMEM - out of memory + + Quindi, se volete che le righe vengano effettivamente generate, dovete + utilizzare una lista ReST, ad esempio:: + + * Return: + * * 0 - OK to runtime suspend the device + * * -EBUSY - Device should not be runtime suspended + + #) Se il vostro testo ha delle righe che iniziano con una frase seguita dai + due punti, allora ognuna di queste frasi verrà considerata come il nome + di una nuova sezione, e probabilmente non produrrà gli effetti desiderati. + +Documentare strutture, unioni ed enumerazioni +--------------------------------------------- + +Generalmente il formato di un commento kernel-doc per struct, union ed enum è:: + + /** + * struct struct_name - Brief description. + * @member1: Description of member1. + * @member2: Description of member2. + * One can provide multiple line descriptions + * for members. + * + * Description of the structure. + */ + +Nell'esempio qui sopra, potete sostituire ``struct`` con ``union`` o ``enum`` +per descrivere unioni ed enumerati. ``member`` viene usato per indicare i +membri di strutture ed unioni, ma anche i valori di un tipo enumerato. + +La descrizione introduttiva (*brief description*) che segue il nome della +funzione può continuare su righe successive e termina con la descrizione di +un argomento, una linea di commento vuota, oppure la fine del commento. + +Membri +~~~~~~ + +I membri di strutture, unioni ed enumerati devo essere documentati come i +parametri delle funzioni; seguono la descrizione introduttiva e possono +estendersi su più righe. + +All'interno d'una struttura o d'un unione, potete utilizzare le etichette +``private:`` e ``public:``. I campi che sono nell'area ``private:`` non +verranno inclusi nella documentazione finale. + +Le etichette ``private:`` e ``public:`` devono essere messe subito dopo +il marcatore di un commento ``/*``. Opzionalmente, possono includere commenti +fra ``:`` e il marcatore di fine commento ``*/``. + +Esempio:: + + /** + * struct my_struct - short description + * @a: first member + * @b: second member + * @d: fourth member + * + * Longer description + */ + struct my_struct { + int a; + int b; + /* private: internal use only */ + int c; + /* public: the next one is public */ + int d; + }; + +Strutture ed unioni annidate +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +È possibile documentare strutture ed unioni annidate, ad esempio:: + + /** + * struct nested_foobar - a struct with nested unions and structs + * @memb1: first member of anonymous union/anonymous struct + * @memb2: second member of anonymous union/anonymous struct + * @memb3: third member of anonymous union/anonymous struct + * @memb4: fourth member of anonymous union/anonymous struct + * @bar: non-anonymous union + * @bar.st1: struct st1 inside @bar + * @bar.st2: struct st2 inside @bar + * @bar.st1.memb1: first member of struct st1 on union bar + * @bar.st1.memb2: second member of struct st1 on union bar + * @bar.st2.memb1: first member of struct st2 on union bar + * @bar.st2.memb2: second member of struct st2 on union bar + */ + struct nested_foobar { + /* Anonymous union/struct*/ + union { + struct { + int memb1; + int memb2; + } + struct { + void *memb3; + int memb4; + } + } + union { + struct { + int memb1; + int memb2; + } st1; + struct { + void *memb1; + int memb2; + } st2; + } bar; + }; + +.. note:: + + #) Quando documentate una struttura od unione annidata, ad esempio + di nome ``foo``, il suo campo ``bar`` dev'essere documentato + usando ``@foo.bar:`` + #) Quando la struttura od unione annidata è anonima, il suo campo + ``bar`` dev'essere documentato usando ``@bar:`` + +Commenti in linea per la documentazione dei membri +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +I membri d'una struttura possono essere documentati in linea all'interno +della definizione stessa. Ci sono due stili: una singola riga di commento +che inizia con ``/**`` e finisce con ``*/``; commenti multi riga come +qualsiasi altro commento kernel-doc:: + + /** + * struct foo - Brief description. + * @foo: The Foo member. + */ + struct foo { + int foo; + /** + * @bar: The Bar member. + */ + int bar; + /** + * @baz: The Baz member. + * + * Here, the member description may contain several paragraphs. + */ + int baz; + union { + /** @foobar: Single line description. */ + int foobar; + }; + /** @bar2: Description for struct @bar2 inside @foo */ + struct { + /** + * @bar2.barbar: Description for @barbar inside @foo.bar2 + */ + int barbar; + } bar2; + }; + + +Documentazione dei tipi di dato +------------------------------- +Generalmente il formato di un commento kernel-doc per typedef è +il seguente:: + + /** + * typedef type_name - Brief description. + * + * Description of the type. + */ + +Anche i tipi di dato per prototipi di funzione possono essere documentati:: + + /** + * typedef type_name - Brief description. + * @arg1: description of arg1 + * @arg2: description of arg2 + * + * Description of the type. + * + * Context: Locking context. + * Return: Meaning of the return value. + */ + typedef void (*type_name)(struct v4l2_ctrl *arg1, void *arg2); + +Marcatori e riferimenti +----------------------- + +All'interno dei commenti di tipo kernel-doc vengono riconosciuti i seguenti +*pattern* che vengono convertiti in marcatori reStructuredText ed in riferimenti +del `dominio Sphinx per il C`_. + +.. attention:: Questi sono riconosciuti **solo** all'interno di commenti + kernel-doc, e **non** all'interno di documenti reStructuredText. + +``funcname()`` + Riferimento ad una funzione. + +``@parameter`` + Nome di un parametro di una funzione (nessun riferimento, solo formattazione). + +``%CONST`` + Il nome di una costante (nessun riferimento, solo formattazione) + +````literal```` + Un blocco di testo che deve essere riportato così com'è. La rappresentazione + finale utilizzerà caratteri a ``spaziatura fissa``. + + Questo è utile se dovete utilizzare caratteri speciali che altrimenti + potrebbero assumere un significato diverso in kernel-doc o in reStructuredText + + Questo è particolarmente utile se dovete scrivere qualcosa come ``%ph`` + all'interno della descrizione di una funzione. + +``$ENVVAR`` + Il nome di una variabile d'ambiente (nessun riferimento, solo formattazione). + +``&struct name`` + Riferimento ad una struttura. + +``&enum name`` + Riferimento ad un'enumerazione. + +``&typedef name`` + Riferimento ad un tipo di dato. + +``&struct_name->member`` or ``&struct_name.member`` + Riferimento ad un membro di una struttura o di un'unione. Il riferimento sarà + la struttura o l'unione, non il memembro. + +``&name`` + Un generico riferimento ad un tipo. Usate, preferibilmente, il riferimento + completo come descritto sopra. Questo è dedicato ai commenti obsoleti. + +Riferimenti usando reStructuredText +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Nei documenti reStructuredText non serve alcuna sintassi speciale per +fare riferimento a funzioni e tipi definiti nei commenti +kernel-doc. Sarà sufficiente terminare i nomi di funzione con ``()``, +e scrivere ``struct``, ``union``, ``enum``, o ``typedef`` prima di un +tipo. Per esempio:: + + See foo() + See struct foo. + See union bar. + See enum baz. + See typedef meh. + +Tuttavia, la personalizzazione dei collegamenti è possibile solo con +la seguente sintassi:: + + See :c:func:`my custom link text for function foo `. + See :c:type:`my custom link text for struct bar `. + + +Commenti per una documentazione generale +---------------------------------------- + +Al fine d'avere il codice ed i commenti nello stesso file, potete includere +dei blocchi di documentazione kernel-doc con un formato libero invece +che nel formato specifico per funzioni, strutture, unioni, enumerati o tipi +di dato. Per esempio, questo tipo di commento potrebbe essere usato per la +spiegazione delle operazioni di un driver o di una libreria + +Questo s'ottiene utilizzando la parola chiave ``DOC:`` a cui viene associato +un titolo. + +Generalmente il formato di un commento generico o di visione d'insieme è +il seguente:: + + /** + * DOC: Theory of Operation + * + * The whizbang foobar is a dilly of a gizmo. It can do whatever you + * want it to do, at any time. It reads your mind. Here's how it works. + * + * foo bar splat + * + * The only drawback to this gizmo is that is can sometimes damage + * hardware, software, or its subject(s). + */ + +Il titolo che segue ``DOC:`` funziona da intestazione all'interno del file +sorgente, ma anche come identificatore per l'estrazione di questi commenti di +documentazione. Quindi, il titolo dev'essere unico all'interno del file. + +======================================= +Includere i commenti di tipo kernel-doc +======================================= + +I commenti di documentazione possono essere inclusi in un qualsiasi documento +di tipo reStructuredText mediante l'apposita direttiva nell'estensione +kernel-doc per Sphinx. + +Le direttive kernel-doc sono nel formato:: + + .. kernel-doc:: source + :option: + +Il campo *source* è il percorso ad un file sorgente, relativo alla cartella +principale dei sorgenti del kernel. La direttiva supporta le seguenti opzioni: + +export: *[source-pattern ...]* + Include la documentazione per tutte le funzioni presenti nel file sorgente + (*source*) che sono state esportate utilizzando ``EXPORT_SYMBOL`` o + ``EXPORT_SYMBOL_GPL`` in *source* o in qualsiasi altro *source-pattern* + specificato. + + Il campo *source-patter* è utile quando i commenti kernel-doc sono stati + scritti nei file d'intestazione, mentre ``EXPORT_SYMBOL`` e + ``EXPORT_SYMBOL_GPL`` si trovano vicino alla definizione delle funzioni. + + Esempi:: + + .. kernel-doc:: lib/bitmap.c + :export: + + .. kernel-doc:: include/net/mac80211.h + :export: net/mac80211/*.c + +internal: *[source-pattern ...]* + Include la documentazione per tutte le funzioni ed i tipi presenti nel file + sorgente (*source*) che **non** sono stati esportati utilizzando + ``EXPORT_SYMBOL`` o ``EXPORT_SYMBOL_GPL`` né in *source* né in qualsiasi + altro *source-pattern* specificato. + + Esempio:: + + .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c + :internal: + +identifiers: *[ function/type ...]* + Include la documentazione per ogni *function* e *type* in *source*. + Se non vengono esplicitamente specificate le funzioni da includere, allora + verranno incluse tutte quelle disponibili in *source*. + + Esempi:: + + .. kernel-doc:: lib/bitmap.c + :identifiers: bitmap_parselist bitmap_parselist_user + + .. kernel-doc:: lib/idr.c + :identifiers: + +functions: *[ function ...]* + Questo è uno pseudonimo, deprecato, per la direttiva 'identifiers'. + +doc: *title* + Include la documentazione del paragrafo ``DOC:`` identificato dal titolo + (*title*) all'interno del file sorgente (*source*). Gli spazi in *title* sono + permessi; non virgolettate *title*. Il campo *title* è utilizzato per + identificare un paragrafo e per questo non viene incluso nella documentazione + finale. Verificate d'avere l'intestazione appropriata nei documenti + reStructuredText. + + Esempio:: + + .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c + :doc: High Definition Audio over HDMI and Display Port + +Senza alcuna opzione, la direttiva kernel-doc include tutti i commenti di +documentazione presenti nel file sorgente (*source*). + +L'estensione kernel-doc fa parte dei sorgenti del kernel, la si può trovare +in ``Documentation/sphinx/kerneldoc.py``. Internamente, viene utilizzato +lo script ``scripts/kernel-doc`` per estrarre i commenti di documentazione +dai file sorgenti. + +Come utilizzare kernel-doc per generare pagine man +-------------------------------------------------- + +Se volete utilizzare kernel-doc solo per generare delle pagine man, potete +farlo direttamente dai sorgenti del kernel:: + + $ scripts/kernel-doc -man $(git grep -l '/\*\*' -- :^Documentation :^tools) | scripts/split-man.pl /tmp/man diff --git a/Documentation/translations/it_IT/doc-guide/parse-headers.rst b/Documentation/translations/it_IT/doc-guide/parse-headers.rst new file mode 100644 index 000000000..993d549ee --- /dev/null +++ b/Documentation/translations/it_IT/doc-guide/parse-headers.rst @@ -0,0 +1,196 @@ +.. include:: ../disclaimer-ita.rst + +.. note:: Per leggere la documentazione originale in inglese: + :ref:`Documentation/doc-guide/index.rst ` + +========================================= +Includere gli i file di intestazione uAPI +========================================= + +Qualche volta è utile includere dei file di intestazione e degli esempi di codice C +al fine di descrivere l'API per lo spazio utente e per generare dei riferimenti +fra il codice e la documentazione. Aggiungere i riferimenti ai file dell'API +dello spazio utente ha ulteriori vantaggi: Sphinx genererà dei messaggi +d'avviso se un simbolo non viene trovato nella documentazione. Questo permette +di mantenere allineate la documentazione della uAPI (API spazio utente) +con le modifiche del kernel. +Il programma :ref:`parse_headers.pl ` genera questi riferimenti. +Esso dev'essere invocato attraverso un Makefile, mentre si genera la +documentazione. Per avere un esempio su come utilizzarlo all'interno del kernel +consultate ``Documentation/userspace-api/media/Makefile``. + +.. _it_parse_headers: + +parse_headers.pl +^^^^^^^^^^^^^^^^ + +NOME +**** + + +parse_headers.pl - analizza i file C al fine di identificare funzioni, +strutture, enumerati e definizioni, e creare riferimenti per Sphinx + +SINTASSI +******** + + +\ **parse_headers.pl**\ [] [] + +Dove può essere: --debug, --usage o --help. + + +OPZIONI +******* + + + +\ **--debug**\ + + Lo script viene messo in modalità verbosa, utile per il debugging. + + +\ **--usage**\ + + Mostra un messaggio d'aiuto breve e termina. + + +\ **--help**\ + + Mostra un messaggio d'aiuto dettagliato e termina. + + +DESCRIZIONE +*********** + +Converte un file d'intestazione o un file sorgente C (C_FILE) in un testo +ReStructuredText incluso mediante il blocco ..parsed-literal +con riferimenti alla documentazione che descrive l'API. Opzionalmente, +il programma accetta anche un altro file (EXCEPTIONS_FILE) che +descrive quali elementi debbano essere ignorati o il cui riferimento +deve puntare ad elemento diverso dal predefinito. + +Il file generato sarà disponibile in (OUT_FILE). + +Il programma è capace di identificare *define*, funzioni, strutture, +tipi di dato, enumerati e valori di enumerati, e di creare i riferimenti +per ognuno di loro. Inoltre, esso è capace di distinguere le #define +utilizzate per specificare i comandi ioctl di Linux. + +Il file EXCEPTIONS_FILE contiene due tipi di dichiarazioni: +\ **ignore**\ o \ **replace**\ . + +La sintassi per ignore è: + +ignore \ **tipo**\ \ **nome**\ + +La dichiarazione \ **ignore**\ significa che non verrà generato alcun +riferimento per il simbolo \ **name**\ di tipo \ **tipo**\ . + + +La sintassi per replace è: + +replace \ **tipo**\ \ **nome**\ \ **nuovo_valore**\ + +La dichiarazione \ **replace**\ significa che verrà generato un +riferimento per il simbolo \ **name**\ di tipo \ **tipo**\ , ma, invece +di utilizzare il valore predefinito, verrà utilizzato il valore +\ **nuovo_valore**\ . + +Per entrambe le dichiarazioni, il \ **tipo**\ può essere uno dei seguenti: + + +\ **ioctl**\ + + La dichiarazione ignore o replace verrà applicata su definizioni di ioctl + come la seguente: + + #define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) + + + +\ **define**\ + + La dichiarazione ignore o replace verrà applicata su una qualsiasi #define + trovata in C_FILE. + + + +\ **typedef**\ + + La dichiarazione ignore o replace verrà applicata ad una dichiarazione typedef + in C_FILE. + + + +\ **struct**\ + + La dichiarazione ignore o replace verrà applicata ai nomi di strutture + in C_FILE. + + + +\ **enum**\ + + La dichiarazione ignore o replace verrà applicata ai nomi di enumerati + in C_FILE. + + + +\ **symbol**\ + + La dichiarazione ignore o replace verrà applicata ai nomi di valori di + enumerati in C_FILE. + + Per le dichiarazioni di tipo replace, il campo \ **new_value**\ utilizzerà + automaticamente i riferimenti :c:type: per \ **typedef**\ , \ **enum**\ e + \ **struct**\. Invece, utilizzerà :ref: per \ **ioctl**\ , \ **define**\ e + \ **symbol**\. Il tipo di riferimento può essere definito esplicitamente + nella dichiarazione stessa. + + +ESEMPI +****** + + +ignore define _VIDEODEV2_H + + +Ignora una definizione #define _VIDEODEV2_H nel file C_FILE. + +ignore symbol PRIVATE + + +In un enumerato come il seguente: + +enum foo { BAR1, BAR2, PRIVATE }; + +Non genererà alcun riferimento per \ **PRIVATE**\ . + +replace symbol BAR1 :c:type:\`foo\` +replace symbol BAR2 :c:type:\`foo\` + + +In un enumerato come il seguente: + +enum foo { BAR1, BAR2, PRIVATE }; + +Genererà un riferimento ai valori BAR1 e BAR2 dal simbolo foo nel dominio C. + + +BUGS +**** + +Riferire ogni malfunzionamento a Mauro Carvalho Chehab + + +COPYRIGHT +********* + + +Copyright (c) 2016 by Mauro Carvalho Chehab . + +Licenza GPLv2: GNU GPL version 2 . + +Questo è software libero: siete liberi di cambiarlo e ridistribuirlo. +Non c'è alcuna garanzia, nei limiti permessi dalla legge. diff --git a/Documentation/translations/it_IT/doc-guide/sphinx.rst b/Documentation/translations/it_IT/doc-guide/sphinx.rst new file mode 100644 index 000000000..64528790d --- /dev/null +++ b/Documentation/translations/it_IT/doc-guide/sphinx.rst @@ -0,0 +1,489 @@ +.. include:: ../disclaimer-ita.rst + +.. note:: Per leggere la documentazione originale in inglese: + :ref:`Documentation/doc-guide/index.rst ` + +.. _it_sphinxdoc: + +============================================= +Usare Sphinx per la documentazione del kernel +============================================= + +Il kernel Linux usa `Sphinx`_ per la generazione della documentazione a partire +dai file `reStructuredText`_ che si trovano nella cartella ``Documentation``. +Per generare la documentazione in HTML o PDF, usate comandi ``make htmldocs`` o +``make pdfdocs``. La documentazione così generata sarà disponibile nella +cartella ``Documentation/output``. + +.. _Sphinx: http://www.sphinx-doc.org/ +.. _reStructuredText: http://docutils.sourceforge.net/rst.html + +I file reStructuredText possono contenere delle direttive che permettono di +includere i commenti di documentazione, o di tipo kernel-doc, dai file +sorgenti. +Solitamente questi commenti sono utilizzati per descrivere le funzioni, i tipi +e l'architettura del codice. I commenti di tipo kernel-doc hanno una struttura +e formato speciale, ma a parte questo vengono processati come reStructuredText. + +Inoltre, ci sono migliaia di altri documenti in formato testo sparsi nella +cartella ``Documentation``. Alcuni di questi verranno probabilmente convertiti, +nel tempo, in formato reStructuredText, ma la maggior parte di questi rimarranno +in formato testo. + +.. _it_sphinx_install: + +Installazione Sphinx +==================== + +I marcatori ReST utilizzati nei file in Documentation/ sono pensati per essere +processati da ``Sphinx`` nella versione 1.7 o superiore. + +Esiste uno script che verifica i requisiti Sphinx. Per ulteriori dettagli +consultate :ref:`it_sphinx-pre-install`. + +La maggior parte delle distribuzioni Linux forniscono Sphinx, ma l'insieme dei +programmi e librerie è fragile e non è raro che dopo un aggiornamento di +Sphinx, o qualche altro pacchetto Python, la documentazione non venga più +generata correttamente. + +Un modo per evitare questo genere di problemi è quello di utilizzare una +versione diversa da quella fornita dalla vostra distribuzione. Per fare questo, +vi raccomandiamo di installare Sphinx dentro ad un ambiente virtuale usando +``virtualenv-3`` o ``virtualenv`` a seconda di come Python 3 è stato +pacchettizzato dalla vostra distribuzione. + +.. note:: + + #) Viene raccomandato l'uso del tema RTD per la documentazione in HTML. + A seconda della versione di Sphinx, potrebbe essere necessaria + l'installazione tramite il comando ``pip install sphinx_rtd_theme``. + + #) Alcune pagine ReST contengono delle formule matematiche. A causa del + modo in cui Sphinx funziona, queste espressioni sono scritte + utilizzando LaTeX. Per una corretta interpretazione, è necessario aver + installato texlive con i pacchetti amdfonts e amsmath. + +Riassumendo, se volete installare la versione 2.4.4 di Sphinx dovete eseguire:: + + $ virtualenv sphinx_2.4.4 + $ . sphinx_2.4.4/bin/activate + (sphinx_2.4.4) $ pip install -r Documentation/sphinx/requirements.txt + +Dopo aver eseguito ``. sphinx_2.4.4/bin/activate``, il prompt cambierà per +indicare che state usando il nuovo ambiente. Se aprite un nuova sessione, +prima di generare la documentazione, dovrete rieseguire questo comando per +rientrare nell'ambiente virtuale. + +Generazione d'immagini +---------------------- + +Il meccanismo che genera la documentazione del kernel contiene un'estensione +capace di gestire immagini in formato Graphviz e SVG (per maggior informazioni +vedere :ref:`it_sphinx_kfigure`). + +Per far si che questo funzioni, dovete installare entrambe i pacchetti +Graphviz e ImageMagick. Il sistema di generazione della documentazione è in +grado di procedere anche se questi pacchetti non sono installati, ma il +risultato, ovviamente, non includerà le immagini. + +Generazione in PDF e LaTeX +-------------------------- + +Al momento, la generazione di questi documenti è supportata solo dalle +versioni di Sphinx superiori alla 2.4. + +Per la generazione di PDF e LaTeX, avrete bisogno anche del pacchetto +``XeLaTeX`` nella versione 3.14159265 + +Per alcune distribuzioni Linux potrebbe essere necessario installare +anche una serie di pacchetti ``texlive`` in modo da fornire il supporto +minimo per il funzionamento di ``XeLaTeX``. + +.. _it_sphinx-pre-install: + +Verificare le dipendenze Sphinx +------------------------------- + +Esiste uno script che permette di verificare automaticamente le dipendenze di +Sphinx. Se lo script riesce a riconoscere la vostra distribuzione, allora +sarà in grado di darvi dei suggerimenti su come procedere per completare +l'installazione:: + + $ ./scripts/sphinx-pre-install + Checking if the needed tools for Fedora release 26 (Twenty Six) are available + Warning: better to also install "texlive-luatex85". + You should run: + + sudo dnf install -y texlive-luatex85 + /usr/bin/virtualenv sphinx_2.4.4 + . sphinx_2.4.4/bin/activate + pip install -r Documentation/sphinx/requirements.txt + + Can't build as 1 mandatory dependency is missing at ./scripts/sphinx-pre-install line 468. + +L'impostazione predefinita prevede il controllo dei requisiti per la generazione +di documenti html e PDF, includendo anche il supporto per le immagini, le +espressioni matematiche e LaTeX; inoltre, presume che venga utilizzato un +ambiente virtuale per Python. I requisiti per generare i documenti html +sono considerati obbligatori, gli altri sono opzionali. + +Questo script ha i seguenti parametri: + +``--no-pdf`` + Disabilita i controlli per la generazione di PDF; + +``--no-virtualenv`` + Utilizza l'ambiente predefinito dal sistema operativo invece che + l'ambiente virtuale per Python; + + +Generazione della documentazione Sphinx +======================================= + +Per generare la documentazione in formato HTML o PDF si eseguono i rispettivi +comandi ``make htmldocs`` o ``make pdfdocs``. Esistono anche altri formati +in cui è possibile generare la documentazione; per maggiori informazioni +potere eseguire il comando ``make help``. +La documentazione così generata sarà disponibile nella sottocartella +``Documentation/output``. + +Ovviamente, per generare la documentazione, Sphinx (``sphinx-build``) +dev'essere installato. Se disponibile, il tema *Read the Docs* per Sphinx +verrà utilizzato per ottenere una documentazione HTML più gradevole. +Per la documentazione in formato PDF, invece, avrete bisogno di ``XeLaTeX` +e di ``convert(1)`` disponibile in ImageMagick (https://www.imagemagick.org). +Tipicamente, tutti questi pacchetti sono disponibili e pacchettizzati nelle +distribuzioni Linux. + +Per poter passare ulteriori opzioni a Sphinx potete utilizzare la variabile +make ``SPHINXOPTS``. Per esempio, se volete che Sphinx sia più verboso durante +la generazione potete usare il seguente comando ``make SPHINXOPTS=-v htmldocs``. + +Potete anche personalizzare l'ouptut html passando un livello aggiuntivo +DOCS_CSS usando la rispettiva variabile d'ambiente ``DOCS_CSS``. + +Potete eliminare la documentazione generata tramite il comando +``make cleandocs``. + +Scrivere la documentazione +========================== + +Aggiungere nuova documentazione è semplice: + +1. aggiungete un file ``.rst`` nella sottocartella ``Documentation`` +2. aggiungete un riferimento ad esso nell'indice (`TOC tree`_) in + ``Documentation/index.rst``. + +.. _TOC tree: http://www.sphinx-doc.org/en/stable/markup/toctree.html + +Questo, di solito, è sufficiente per la documentazione più semplice (come +quella che state leggendo ora), ma per una documentazione più elaborata è +consigliato creare una sottocartella dedicata (o, quando possibile, utilizzarne +una già esistente). Per esempio, il sottosistema grafico è documentato nella +sottocartella ``Documentation/gpu``; questa documentazione è divisa in +diversi file ``.rst`` ed un indice ``index.rst`` (con un ``toctree`` +dedicato) a cui si fa riferimento nell'indice principale. + +Consultate la documentazione di `Sphinx`_ e `reStructuredText`_ per maggiori +informazione circa le loro potenzialità. In particolare, il +`manuale introduttivo a reStructuredText`_ di Sphinx è un buon punto da +cui cominciare. Esistono, inoltre, anche alcuni +`costruttori specifici per Sphinx`_. + +.. _`manuale introduttivo a reStructuredText`: http://www.sphinx-doc.org/en/stable/rest.html +.. _`costruttori specifici per Sphinx`: http://www.sphinx-doc.org/en/stable/markup/index.html + +Guide linea per la documentazione del kernel +-------------------------------------------- + +In questa sezione troverete alcune linee guida specifiche per la documentazione +del kernel: + +* Non esagerate con i costrutti di reStructuredText. Mantenete la + documentazione semplice. La maggior parte della documentazione dovrebbe + essere testo semplice con una strutturazione minima che permetta la + conversione in diversi formati. + +* Mantenete la strutturazione il più fedele possibile all'originale quando + convertite un documento in formato reStructuredText. + +* Aggiornate i contenuti quando convertite della documentazione, non limitatevi + solo alla formattazione. + +* Mantenete la decorazione dei livelli di intestazione come segue: + + 1. ``=`` con una linea superiore per il titolo del documento:: + + ====== + Titolo + ====== + + 2. ``=`` per i capitoli:: + + Capitoli + ======== + + 3. ``-`` per le sezioni:: + + Sezioni + ------- + + 4. ``~`` per le sottosezioni:: + + Sottosezioni + ~~~~~~~~~~~~ + + Sebbene RST non forzi alcun ordine specifico (*Piuttosto che imporre + un numero ed un ordine fisso di decorazioni, l'ordine utilizzato sarà + quello incontrato*), avere uniformità dei livelli principali rende più + semplice la lettura dei documenti. + +* Per inserire blocchi di testo con caratteri a dimensione fissa (codici di + esempio, casi d'uso, eccetera): utilizzate ``::`` quando non è necessario + evidenziare la sintassi, specialmente per piccoli frammenti; invece, + utilizzate ``.. code-block:: `` per blocchi più lunghi che + beneficeranno della sintassi evidenziata. Per un breve pezzo di codice da + inserire nel testo, usate \`\`. + + +Il dominio C +------------ + +Il **Dominio Sphinx C** (denominato c) è adatto alla documentazione delle API C. +Per esempio, un prototipo di una funzione: + +.. code-block:: rst + + .. c:function:: int ioctl( int fd, int request ) + +Il dominio C per kernel-doc ha delle funzionalità aggiuntive. Per esempio, +potete assegnare un nuovo nome di riferimento ad una funzione con un nome +molto comune come ``open`` o ``ioctl``: + +.. code-block:: rst + + .. c:function:: int ioctl( int fd, int request ) + :name: VIDIOC_LOG_STATUS + +Il nome della funzione (per esempio ioctl) rimane nel testo ma il nome del suo +riferimento cambia da ``ioctl`` a ``VIDIOC_LOG_STATUS``. Anche la voce +nell'indice cambia in ``VIDIOC_LOG_STATUS``. + +Notate che per una funzione non c'è bisogno di usare ``c:func:`` per generarne +i riferimenti nella documentazione. Grazie a qualche magica estensione a +Sphinx, il sistema di generazione della documentazione trasformerà +automaticamente un riferimento ad una ``funzione()`` in un riferimento +incrociato quando questa ha una voce nell'indice. Se trovate degli usi di +``c:func:`` nella documentazione del kernel, sentitevi liberi di rimuoverli. + + +Tabelle a liste +--------------- + +Il formato ``list-table`` può essere utile per tutte quelle tabelle che non +possono essere facilmente scritte usando il formato ASCII-art di Sphinx. Però, +questo genere di tabelle sono illeggibili per chi legge direttamente i file di +testo. Dunque, questo formato dovrebbe essere evitato senza forti argomenti che +ne giustifichino l'uso. + +La ``flat-table`` è anch'essa una lista di liste simile alle ``list-table`` +ma con delle funzionalità aggiuntive: + +* column-span: col ruolo ``cspan`` una cella può essere estesa attraverso + colonne successive + +* raw-span: col ruolo ``rspan`` una cella può essere estesa attraverso + righe successive + +* auto-span: la cella più a destra viene estesa verso destra per compensare + la mancanza di celle. Con l'opzione ``:fill-cells:`` questo comportamento + può essere cambiato da *auto-span* ad *auto-fill*, il quale inserisce + automaticamente celle (vuote) invece che estendere l'ultima. + +opzioni: + +* ``:header-rows:`` [int] conta le righe di intestazione +* ``:stub-columns:`` [int] conta le colonne di stub +* ``:widths:`` [[int] [int] ... ] larghezza delle colonne +* ``:fill-cells:`` invece di estendere automaticamente una cella su quelle + mancanti, ne crea di vuote. + +ruoli: + +* ``:cspan:`` [int] colonne successive (*morecols*) +* ``:rspan:`` [int] righe successive (*morerows*) + +L'esempio successivo mostra come usare questo marcatore. Il primo livello della +nostra lista di liste è la *riga*. In una *riga* è possibile inserire solamente +la lista di celle che compongono la *riga* stessa. Fanno eccezione i *commenti* +( ``..`` ) ed i *collegamenti* (per esempio, un riferimento a +``:ref:`last row ``` / :ref:`last row `) + +.. code-block:: rst + + .. flat-table:: table title + :widths: 2 1 1 3 + + * - head col 1 + - head col 2 + - head col 3 + - head col 4 + + * - row 1 + - field 1.1 + - field 1.2 with autospan + + * - row 2 + - field 2.1 + - :rspan:`1` :cspan:`1` field 2.2 - 3.3 + + * .. _`it last row`: + + - row 3 + +Che verrà rappresentata nel seguente modo: + + .. flat-table:: table title + :widths: 2 1 1 3 + + * - head col 1 + - head col 2 + - head col 3 + - head col 4 + + * - row 1 + - field 1.1 + - field 1.2 with autospan + + * - row 2 + - field 2.1 + - :rspan:`1` :cspan:`1` field 2.2 - 3.3 + + * .. _`it last row`: + + - row 3 + +Riferimenti incrociati +---------------------- + +Aggiungere un riferimento incrociato da una pagina della +documentazione ad un'altra può essere fatto scrivendo il percorso al +file corrispondende, non serve alcuna sintassi speciale. Si possono +usare sia percorsi assoluti che relativi. Quelli assoluti iniziano con +"documentation/". Per esempio, potete fare riferimento a questo +documento in uno dei seguenti modi (da notare che l'estensione +``.rst`` è necessaria):: + + Vedere Documentation/doc-guide/sphinx.rst. Questo funziona sempre + Guardate pshinx.rst, che si trova nella stessa cartella. + Leggete ../sphinx.rst, che si trova nella cartella precedente. + +Se volete che il collegamento abbia un testo diverso rispetto al +titolo del documento, allora dovrete usare la direttiva Sphinx +``doc``. Per esempio:: + + Vedere :doc:`il mio testo per il collegamento `. + +Nella maggioranza dei casi si consiglia il primo metodo perché è più +pulito ed adatto a chi legge dai sorgenti. Se incontrare un ``:doc:`` +che non da alcun valore, sentitevi liberi di convertirlo in un +percorso al documento. + +Per informazioni riguardo ai riferimenti incrociati ai commenti +kernel-doc per funzioni o tipi, consultate + +.. _it_sphinx_kfigure: + +Figure ed immagini +================== + +Se volete aggiungere un'immagine, utilizzate le direttive ``kernel-figure`` +e ``kernel-image``. Per esempio, per inserire una figura di un'immagine in +formato SVG (:ref:`it_svg_image_example`):: + + .. kernel-figure:: ../../../doc-guide/svg_image.svg + :alt: una semplice immagine SVG + + Una semplice immagine SVG + +.. _it_svg_image_example: + +.. kernel-figure:: ../../../doc-guide/svg_image.svg + :alt: una semplice immagine SVG + + Una semplice immagine SVG + +Le direttive del kernel per figure ed immagini supportano il formato **DOT**, +per maggiori informazioni + +* DOT: http://graphviz.org/pdf/dotguide.pdf +* Graphviz: http://www.graphviz.org/content/dot-language + +Un piccolo esempio (:ref:`it_hello_dot_file`):: + + .. kernel-figure:: ../../../doc-guide/hello.dot + :alt: ciao mondo + + Esempio DOT + +.. _it_hello_dot_file: + +.. kernel-figure:: ../../../doc-guide/hello.dot + :alt: ciao mondo + + Esempio DOT + +Tramite la direttiva ``kernel-render`` è possibile aggiungere codice specifico; +ad esempio nel formato **DOT** di Graphviz.:: + + .. kernel-render:: DOT + :alt: foobar digraph + :caption: Codice **DOT** (Graphviz) integrato + + digraph foo { + "bar" -> "baz"; + } + +La rappresentazione dipenderà dei programmi installati. Se avete Graphviz +installato, vedrete un'immagine vettoriale. In caso contrario, il codice grezzo +verrà rappresentato come *blocco testuale* (:ref:`it_hello_dot_render`). + +.. _it_hello_dot_render: + +.. kernel-render:: DOT + :alt: foobar digraph + :caption: Codice **DOT** (Graphviz) integrato + + digraph foo { + "bar" -> "baz"; + } + +La direttiva *render* ha tutte le opzioni della direttiva *figure*, con +l'aggiunta dell'opzione ``caption``. Se ``caption`` ha un valore allora +un nodo *figure* viene aggiunto. Altrimenti verrà aggiunto un nodo *image*. +L'opzione ``caption`` è necessaria in caso si vogliano aggiungere dei +riferimenti (:ref:`it_hello_svg_render`). + +Per la scrittura di codice **SVG**:: + + .. kernel-render:: SVG + :caption: Integrare codice **SVG** + :alt: so-nw-arrow + + + + ... + + +.. _it_hello_svg_render: + +.. kernel-render:: SVG + :caption: Integrare codice **SVG** + :alt: so-nw-arrow + + + + + + diff --git a/Documentation/translations/it_IT/index.rst b/Documentation/translations/it_IT/index.rst new file mode 100644 index 000000000..e80a3097a --- /dev/null +++ b/Documentation/translations/it_IT/index.rst @@ -0,0 +1,141 @@ +.. _it_linux_doc: + +=================== +Traduzione italiana +=================== + +.. raw:: latex + + \kerneldocCJKoff + +:manutentore: Federico Vaga + +.. _it_disclaimer: + +Avvertenze +========== + +L'obiettivo di questa traduzione è di rendere più facile la lettura e +la comprensione per chi non capisce l'inglese o ha dubbi sulla sua +interpretazione, oppure semplicemente per chi preferisce leggere in lingua +italiana. Tuttavia, tenete ben presente che l'*unica* documentazione +ufficiale è quella in lingua inglese: :ref:`linux_doc` + +La propagazione simultanea a tutte le traduzioni di una modifica in +:ref:`linux_doc` è altamente improbabile. I manutentori delle traduzioni - +e i contributori - seguono l'evolversi della documentazione ufficiale e +cercano di mantenere le rispettive traduzioni allineate nel limite del +possibile. Per questo motivo non c'è garanzia che una traduzione sia +aggiornata all'ultima modifica. Se quello che leggete in una traduzione +non corrisponde a quello che leggete nel codice, informate il manutentore +della traduzione e - se potete - verificate anche la documentazione in +inglese. + +Una traduzione non è un *fork* della documentazione ufficiale, perciò gli +utenti non vi troveranno alcuna informazione diversa rispetto alla versione +ufficiale. Ogni aggiunta, rimozione o modifica dei contenuti deve essere +fatta prima nei documenti in inglese. In seguito, e quando è possibile, la +stessa modifica dovrebbe essere applicata anche alle traduzioni. I manutentori +delle traduzioni accettano contributi che interessano prettamente l'attività +di traduzione (per esempio, nuove traduzioni, aggiornamenti, correzioni). + +Le traduzioni cercano di essere il più possibile accurate ma non è possibile +mappare direttamente una lingua in un'altra. Ogni lingua ha la sua grammatica +e una sua cultura alle spalle, quindi la traduzione di una frase in inglese +potrebbe essere modificata per adattarla all'italiano. Per questo motivo, +quando leggete questa traduzione, potreste trovare alcune differenze di forma +ma che trasmettono comunque il messaggio originale. Nonostante la grande +diffusione di inglesismi nella lingua parlata, quando possibile, questi +verranno sostituiti dalle corrispettive parole italiane + +Se avete bisogno d'aiuto per comunicare con la comunità Linux ma non vi sentite +a vostro agio nello scrivere in inglese, potete chiedere aiuto al manutentore +della traduzione. + +La documentazione del kernel Linux +================================== + +Questo è il livello principale della documentazione del kernel in +lingua italiana. La traduzione è incompleta, noterete degli avvisi +che vi segnaleranno la mancanza di una traduzione o di un gruppo di +traduzioni. + +Più in generale, la documentazione, come il kernel stesso, sono in +costante sviluppo; particolarmente vero in quanto stiamo lavorando +alla riorganizzazione della documentazione in modo più coerente. +I miglioramenti alla documentazione sono sempre i benvenuti; per cui, +se vuoi aiutare, iscriviti alla lista di discussione linux-doc presso +vger.kernel.org. + +Documentazione sulla licenza dei sorgenti +----------------------------------------- + +I seguenti documenti descrivono la licenza usata nei sorgenti del kernel Linux +(GPLv2), come licenziare i singoli file; inoltre troverete i riferimenti al +testo integrale della licenza. + +* :ref:`it_kernel_licensing` + +Documentazione per gli utenti +----------------------------- + +I seguenti manuali sono scritti per gli *utenti* del kernel - ovvero, +coloro che cercano di farlo funzionare in modo ottimale su un dato sistema + +.. warning:: + + TODO ancora da tradurre + +Documentazione per gli sviluppatori di applicazioni +--------------------------------------------------- + +Il manuale delle API verso lo spazio utente è una collezione di documenti +che descrivono le interfacce del kernel viste dagli sviluppatori +di applicazioni. + +.. warning:: + + TODO ancora da tradurre + + +Introduzione allo sviluppo del kernel +------------------------------------- + +Questi manuali contengono informazioni su come contribuire allo sviluppo +del kernel. +Attorno al kernel Linux gira una comunità molto grande con migliaia di +sviluppatori che contribuiscono ogni anno. Come in ogni grande comunità, +sapere come le cose vengono fatte renderà il processo di integrazione delle +vostre modifiche molto più semplice + +.. toctree:: + :maxdepth: 2 + + process/index + doc-guide/index + kernel-hacking/index + +Documentazione della API del kernel +----------------------------------- + +Questi manuali forniscono dettagli su come funzionano i sottosistemi del +kernel dal punto di vista degli sviluppatori del kernel. Molte delle +informazioni contenute in questi manuali sono prese direttamente dai +file sorgenti, informazioni aggiuntive vengono aggiunte solo se necessarie +(o almeno ci proviamo — probabilmente *non* tutto quello che è davvero +necessario). + +.. toctree:: + :maxdepth: 2 + + core-api/index + +Documentazione specifica per architettura +----------------------------------------- + +Questi manuali forniscono dettagli di programmazione per le diverse +implementazioni d'architettura. + +.. warning:: + + TODO ancora da tradurre diff --git a/Documentation/translations/it_IT/kernel-hacking/hacking.rst b/Documentation/translations/it_IT/kernel-hacking/hacking.rst new file mode 100644 index 000000000..560f1d048 --- /dev/null +++ b/Documentation/translations/it_IT/kernel-hacking/hacking.rst @@ -0,0 +1,870 @@ +.. include:: ../disclaimer-ita.rst + +.. note:: Per leggere la documentazione originale in inglese: + :ref:`Documentation/kernel-hacking/hacking.rst ` + +:Original: :ref:`Documentation/kernel-hacking/hacking.rst ` +:Translator: Federico Vaga + +.. _it_kernel_hacking_hack: + +================================================= +L'inaffidabile guida all'hacking del kernel Linux +================================================= + +:Author: Rusty Russell + +Introduzione +============ + +Benvenuto, gentile lettore, alla notevole ed inaffidabile guida all'hacking +del kernel Linux ad opera di Rusty. Questo documento descrive le procedure +più usate ed i concetti necessari per scrivere codice per il kernel: lo scopo +è di fornire ai programmatori C più esperti un manuale di base per sviluppo. +Eviterò dettagli implementativi: per questo abbiamo il codice, +ed ignorerò intere parti di alcune procedure. + +Prima di leggere questa guida, sappiate che non ho mai voluto scriverla, +essendo esageratamente sotto qualificato, ma ho sempre voluto leggere +qualcosa di simile, e quindi questa era l'unica via. Spero che possa +crescere e diventare un compendio di buone pratiche, punti di partenza +e generiche informazioni. + +Gli attori +========== + +In qualsiasi momento ognuna delle CPU di un sistema può essere: + +- non associata ad alcun processo, servendo un'interruzione hardware; + +- non associata ad alcun processo, servendo un softirq o tasklet; + +- in esecuzione nello spazio kernel, associata ad un processo + (contesto utente); + +- in esecuzione di un processo nello spazio utente; + +Esiste un ordine fra questi casi. Gli ultimi due possono avvicendarsi (preempt) +l'un l'altro, ma a parte questo esiste una gerarchia rigida: ognuno di questi +può avvicendarsi solo ad uno di quelli sottostanti. Per esempio, mentre un +softirq è in esecuzione su d'una CPU, nessun altro softirq può avvicendarsi +nell'esecuzione, ma un'interruzione hardware può. Ciò nonostante, le altre CPU +del sistema operano indipendentemente. + +Più avanti vedremo alcuni modi in cui dal contesto utente è possibile bloccare +le interruzioni, così da impedirne davvero il diritto di prelazione. + +Contesto utente +--------------- + +Ci si trova nel contesto utente quando si arriva da una chiamata di sistema +od altre eccezioni: come nello spazio utente, altre procedure più importanti, +o le interruzioni, possono far valere il proprio diritto di prelazione sul +vostro processo. Potete sospendere l'esecuzione chiamando :c:func:`schedule()`. + +.. note:: + + Si è sempre in contesto utente quando un modulo viene caricato o rimosso, + e durante le operazioni nello strato dei dispositivi a blocchi + (*block layer*). + +Nel contesto utente, il puntatore ``current`` (il quale indica il processo al +momento in esecuzione) è valido, e :c:func:`in_interrupt()` +(``include/linux/preempt.h``) è falsa. + +.. warning:: + + Attenzione che se avete la prelazione o i softirq disabilitati (vedere + di seguito), :c:func:`in_interrupt()` ritornerà un falso positivo. + +Interruzioni hardware (Hard IRQs) +--------------------------------- + +Temporizzatori, schede di rete e tastiere sono esempi di vero hardware +che possono produrre interruzioni in un qualsiasi momento. Il kernel esegue +i gestori d'interruzione che prestano un servizio all'hardware. Il kernel +garantisce che questi gestori non vengano mai interrotti: se una stessa +interruzione arriva, questa verrà accodata (o scartata). +Dato che durante la loro esecuzione le interruzioni vengono disabilitate, +i gestori d'interruzioni devono essere veloci: spesso si limitano +esclusivamente a notificare la presa in carico dell'interruzione, +programmare una 'interruzione software' per l'esecuzione e quindi terminare. + +Potete dire d'essere in una interruzione hardware perché in_hardirq() +ritorna vero. + +.. warning:: + + Attenzione, questa ritornerà un falso positivo se le interruzioni + sono disabilitate (vedere di seguito). + +Contesto d'interruzione software: softirq e tasklet +--------------------------------------------------- + +Quando una chiamata di sistema sta per tornare allo spazio utente, +oppure un gestore d'interruzioni termina, qualsiasi 'interruzione software' +marcata come pendente (solitamente da un'interruzione hardware) viene +eseguita (``kernel/softirq.c``). + +La maggior parte del lavoro utile alla gestione di un'interruzione avviene qui. +All'inizio della transizione ai sistemi multiprocessore, c'erano solo i +cosiddetti 'bottom half' (BH), i quali non traevano alcun vantaggio da questi +sistemi. Non appena abbandonammo i computer raffazzonati con fiammiferi e +cicche, abbandonammo anche questa limitazione e migrammo alle interruzioni +software 'softirqs'. + +Il file ``include/linux/interrupt.h`` elenca i differenti tipi di 'softirq'. +Un tipo di softirq molto importante è il timer (``include/linux/timer.h``): +potete programmarlo per far si che esegua funzioni dopo un determinato +periodo di tempo. + +Dato che i softirq possono essere eseguiti simultaneamente su più di un +processore, spesso diventa estenuante l'averci a che fare. Per questa ragione, +i tasklet (``include/linux/interrupt.h``) vengo usati più di frequente: +possono essere registrati dinamicamente (il che significa che potete averne +quanti ne volete), e garantiscono che un qualsiasi tasklet verrà eseguito +solo su un processore alla volta, sebbene diversi tasklet possono essere +eseguiti simultaneamente. + +.. warning:: + + Il nome 'tasklet' è ingannevole: non hanno niente a che fare + con i 'processi' ('tasks'). + +Potete determinate se siete in un softirq (o tasklet) utilizzando la +macro :c:func:`in_softirq()` (``include/linux/preempt.h``). + +.. warning:: + + State attenti che questa macro ritornerà un falso positivo + se :ref:`botton half lock ` è bloccato. + +Alcune regole basilari +====================== + +Nessuna protezione della memoria + Se corrompete la memoria, che sia in contesto utente o d'interruzione, + la macchina si pianterà. Siete sicuri che quello che volete fare + non possa essere fatto nello spazio utente? + +Nessun numero in virgola mobile o MMX + Il contesto della FPU non è salvato; anche se siete in contesto utente + lo stato dell'FPU probabilmente non corrisponde a quello del processo + corrente: vi incasinerete con lo stato di qualche altro processo. Se + volete davvero usare la virgola mobile, allora dovrete salvare e recuperare + lo stato dell'FPU (ed evitare cambi di contesto). Generalmente è una + cattiva idea; usate l'aritmetica a virgola fissa. + +Un limite rigido dello stack + A seconda della configurazione del kernel lo stack è fra 3K e 6K per la + maggior parte delle architetture a 32-bit; è di 14K per la maggior + parte di quelle a 64-bit; e spesso è condiviso con le interruzioni, + per cui non si può usare. + Evitare profonde ricorsioni ad enormi array locali nello stack + (allocateli dinamicamente). + +Il kernel Linux è portabile + Quindi mantenetelo tale. Il vostro codice dovrebbe essere a 64-bit ed + indipendente dall'ordine dei byte (endianess) di un processore. Inoltre, + dovreste minimizzare il codice specifico per un processore; per esempio + il codice assembly dovrebbe essere incapsulato in modo pulito e minimizzato + per facilitarne la migrazione. Generalmente questo codice dovrebbe essere + limitato alla parte di kernel specifica per un'architettura. + +ioctl: non scrivere nuove chiamate di sistema +============================================= + +Una chiamata di sistema, generalmente, è scritta così:: + + asmlinkage long sys_mycall(int arg) + { + return 0; + } + +Primo, nella maggior parte dei casi non volete creare nuove chiamate di +sistema. +Create un dispositivo a caratteri ed implementate l'appropriata chiamata ioctl. +Questo meccanismo è molto più flessibile delle chiamate di sistema: esso non +dev'essere dichiarato in tutte le architetture nei file +``include/asm/unistd.h`` e ``arch/kernel/entry.S``; inoltre, è improbabile +che questo venga accettato da Linus. + +Se tutto quello che il vostro codice fa è leggere o scrivere alcuni parametri, +considerate l'implementazione di un'interfaccia :c:func:`sysfs()`. + +All'interno di una ioctl vi trovate nel contesto utente di un processo. Quando +avviene un errore dovete ritornare un valore negativo di errno (consultate +``include/uapi/asm-generic/errno-base.h``, +``include/uapi/asm-generic/errno.h`` e ``include/linux/errno.h``), altrimenti +ritornate 0. + +Dopo aver dormito dovreste verificare se ci sono stati dei segnali: il modo +Unix/Linux di gestire un segnale è di uscire temporaneamente dalla chiamata +di sistema con l'errore ``-ERESTARTSYS``. La chiamata di sistema ritornerà +al contesto utente, eseguirà il gestore del segnale e poi la vostra chiamata +di sistema riprenderà (a meno che l'utente non l'abbia disabilitata). Quindi, +dovreste essere pronti per continuare l'esecuzione, per esempio nel mezzo +della manipolazione di una struttura dati. + +:: + + if (signal_pending(current)) + return -ERESTARTSYS; + +Se dovete eseguire dei calcoli molto lunghi: pensate allo spazio utente. +Se **davvero** volete farlo nel kernel ricordatevi di verificare periodicamente +se dovete *lasciare* il processore (ricordatevi che, per ogni processore, c'è +un sistema multi-processo senza diritto di prelazione). +Esempio:: + + cond_resched(); /* Will sleep */ + +Una breve nota sulla progettazione delle interfacce: il motto dei sistemi +UNIX è "fornite meccanismi e non politiche" + +La ricetta per uno stallo +========================= + +Non è permesso invocare una procedura che potrebbe dormire, fanno eccezione +i seguenti casi: + +- Siete in un contesto utente. + +- Non trattenete alcun spinlock. + +- Avete abilitato le interruzioni (in realtà, Andy Kleen dice che + lo schedulatore le abiliterà per voi, ma probabilmente questo non è quello + che volete). + +Da tener presente che alcune funzioni potrebbero dormire implicitamente: +le più comuni sono quelle per l'accesso allo spazio utente (\*_user) e +quelle per l'allocazione della memoria senza l'opzione ``GFP_ATOMIC`` + +Dovreste sempre compilare il kernel con l'opzione ``CONFIG_DEBUG_ATOMIC_SLEEP`` +attiva, questa vi avviserà se infrangete una di queste regole. +Se **infrangete** le regole, allora potreste bloccare il vostro scatolotto. + +Veramente. + +Alcune delle procedure più comuni +================================= + +:c:func:`printk()` +------------------ + +Definita in ``include/linux/printk.h`` + +:c:func:`printk()` fornisce messaggi alla console, dmesg, e al demone syslog. +Essa è utile per il debugging o per la notifica di errori; può essere +utilizzata anche all'interno del contesto d'interruzione, ma usatela con +cautela: una macchina che ha la propria console inondata da messaggi diventa +inutilizzabile. La funzione utilizza un formato stringa quasi compatibile con +la printf ANSI C, e la concatenazione di una stringa C come primo argomento +per indicare la "priorità":: + + printk(KERN_INFO "i = %u\n", i); + +Consultate ``include/linux/kern_levels.h`` per gli altri valori ``KERN_``; +questi sono interpretati da syslog come livelli. Un caso speciale: +per stampare un indirizzo IP usate:: + + __be32 ipaddress; + printk(KERN_INFO "my ip: %pI4\n", &ipaddress); + + +:c:func:`printk()` utilizza un buffer interno di 1K e non s'accorge di +eventuali sforamenti. Accertatevi che vi basti. + +.. note:: + + Saprete di essere un vero hacker del kernel quando inizierete a digitare + nei vostri programmi utenti le printf come se fossero printk :) + +.. note:: + + Un'altra nota a parte: la versione originale di Unix 6 aveva un commento + sopra alla funzione printf: "Printf non dovrebbe essere usata per il + chiacchiericcio". Dovreste seguire questo consiglio. + +:c:func:`copy_to_user()` / :c:func:`copy_from_user()` / :c:func:`get_user()` / :c:func:`put_user()` +--------------------------------------------------------------------------------------------------- + +Definite in ``include/linux/uaccess.h`` / ``asm/uaccess.h`` + +**[DORMONO]** + +:c:func:`put_user()` e :c:func:`get_user()` sono usate per ricevere ed +impostare singoli valori (come int, char, o long) da e verso lo spazio utente. +Un puntatore nello spazio utente non dovrebbe mai essere dereferenziato: i dati +dovrebbero essere copiati usando suddette procedure. Entrambe ritornano +``-EFAULT`` oppure 0. + +:c:func:`copy_to_user()` e :c:func:`copy_from_user()` sono più generiche: +esse copiano una quantità arbitraria di dati da e verso lo spazio utente. + +.. warning:: + + Al contrario di:c:func:`put_user()` e :c:func:`get_user()`, queste + funzioni ritornano la quantità di dati copiati (0 è comunque un successo). + +[Sì, questa interfaccia mi imbarazza. La battaglia torna in auge anno +dopo anno. --RR] + +Le funzioni potrebbero dormire implicitamente. Queste non dovrebbero mai essere +invocate fuori dal contesto utente (non ha senso), con le interruzioni +disabilitate, o con uno spinlock trattenuto. + +:c:func:`kmalloc()`/:c:func:`kfree()` +------------------------------------- + +Definite in ``include/linux/slab.h`` + +**[POTREBBERO DORMIRE: LEGGI SOTTO]** + +Queste procedure sono utilizzate per la richiesta dinamica di un puntatore ad +un pezzo di memoria allineato, esattamente come malloc e free nello spazio +utente, ma :c:func:`kmalloc()` ha un argomento aggiuntivo per indicare alcune +opzioni. Le opzioni più importanti sono: + +``GFP_KERNEL`` + Potrebbe dormire per librarare della memoria. L'opzione fornisce il modo + più affidabile per allocare memoria, ma il suo uso è strettamente limitato + allo spazio utente. + +``GFP_ATOMIC`` + Non dorme. Meno affidabile di ``GFP_KERNEL``, ma può essere usata in un + contesto d'interruzione. Dovreste avere **davvero** una buona strategia + per la gestione degli errori in caso di mancanza di memoria. + +``GFP_DMA`` + Alloca memoria per il DMA sul bus ISA nello spazio d'indirizzamento + inferiore ai 16MB. Se non sapete cos'è allora non vi serve. + Molto inaffidabile. + +Se vedete un messaggio d'avviso per una funzione dormiente che viene chiamata +da un contesto errato, allora probabilmente avete usato una funzione +d'allocazione dormiente da un contesto d'interruzione senza ``GFP_ATOMIC``. +Dovreste correggerlo. Sbrigatevi, non cincischiate. + +Se allocate almeno ``PAGE_SIZE``(``asm/page.h`` o ``asm/page_types.h``) byte, +considerate l'uso di :c:func:`__get_free_pages()` (``include/linux/gfp.h``). +Accetta un argomento che definisce l'ordine (0 per per la dimensione di una +pagine, 1 per una doppia pagina, 2 per quattro pagine, eccetra) e le stesse +opzioni d'allocazione viste precedentemente. + +Se state allocando un numero di byte notevolemnte superiore ad una pagina +potete usare :c:func:`vmalloc()`. Essa allocherà memoria virtuale all'interno +dello spazio kernel. Questo è un blocco di memoria fisica non contiguo, ma +la MMU vi darà l'impressione che lo sia (quindi, sarà contiguo solo dal punto +di vista dei processori, non dal punto di vista dei driver dei dispositivi +esterni). +Se per qualche strana ragione avete davvero bisogno di una grossa quantità di +memoria fisica contigua, avete un problema: Linux non ha un buon supporto per +questo caso d'uso perché, dopo un po' di tempo, la frammentazione della memoria +rende l'operazione difficile. Il modo migliore per allocare un simile blocco +all'inizio dell'avvio del sistema è attraverso la procedura +:c:func:`alloc_bootmem()`. + +Prima di inventare la vostra cache per gli oggetti più usati, considerate +l'uso di una cache slab disponibile in ``include/linux/slab.h``. + +:c:macro:`current` +------------------- + +Definita in ``include/asm/current.h`` + +Questa variabile globale (in realtà una macro) contiene un puntatore alla +struttura del processo corrente, quindi è valido solo dal contesto utente. +Per esempio, quando un processo esegue una chiamata di sistema, questo +punterà alla struttura dati del processo chiamate. +Nel contesto d'interruzione in suo valore **non è NULL**. + +:c:func:`mdelay()`/:c:func:`udelay()` +------------------------------------- + +Definite in ``include/asm/delay.h`` / ``include/linux/delay.h`` + +Le funzioni :c:func:`udelay()` e :c:func:`ndelay()` possono essere utilizzate +per brevi pause. Non usate grandi valori perché rischiate d'avere un +overflow - in questo contesto la funzione :c:func:`mdelay()` è utile, +oppure considerate :c:func:`msleep()`. + +:c:func:`cpu_to_be32()`/:c:func:`be32_to_cpu()`/:c:func:`cpu_to_le32()`/:c:func:`le32_to_cpu()` +----------------------------------------------------------------------------------------------- + +Definite in ``include/asm/byteorder.h`` + +La famiglia di funzioni :c:func:`cpu_to_be32()` (dove "32" può essere +sostituito da 64 o 16, e "be" con "le") forniscono un modo generico +per fare conversioni sull'ordine dei byte (endianess): esse ritornano +il valore convertito. Tutte le varianti supportano anche il processo inverso: +:c:func:`be32_to_cpu()`, eccetera. + +Queste funzioni hanno principalmente due varianti: la variante per +puntatori, come :c:func:`cpu_to_be32p()`, che prende un puntatore +ad un tipo, e ritorna il valore convertito. L'altra variante per +la famiglia di conversioni "in-situ", come :c:func:`cpu_to_be32s()`, +che convertono il valore puntato da un puntatore, e ritornano void. + +:c:func:`local_irq_save()`/:c:func:`local_irq_restore()` +-------------------------------------------------------- + +Definite in ``include/linux/irqflags.h`` + +Queste funzioni abilitano e disabilitano le interruzioni hardware +sul processore locale. Entrambe sono rientranti; esse salvano lo stato +precedente nel proprio argomento ``unsigned long flags``. Se sapete +che le interruzioni sono abilite, potete semplicemente utilizzare +:c:func:`local_irq_disable()` e :c:func:`local_irq_enable()`. + +.. _it_local_bh_disable: + +:c:func:`local_bh_disable()`/:c:func:`local_bh_enable()` +-------------------------------------------------------- + +Definite in ``include/linux/bottom_half.h`` + + +Queste funzioni abilitano e disabilitano le interruzioni software +sul processore locale. Entrambe sono rientranti; se le interruzioni +software erano già state disabilitate in precedenza, rimarranno +disabilitate anche dopo aver invocato questa coppia di funzioni. +Lo scopo è di prevenire l'esecuzione di softirq e tasklet sul processore +attuale. + +:c:func:`smp_processor_id()` +---------------------------- + +Definita in ``include/linux/smp.h`` + +:c:func:`get_cpu()` nega il diritto di prelazione (quindi non potete essere +spostati su un altro processore all'improvviso) e ritorna il numero +del processore attuale, fra 0 e ``NR_CPUS``. Da notare che non è detto +che la numerazione dei processori sia continua. Quando avete terminato, +ritornate allo stato precedente con :c:func:`put_cpu()`. + +Se sapete che non dovete essere interrotti da altri processi (per esempio, +se siete in un contesto d'interruzione, o il diritto di prelazione +è disabilitato) potete utilizzare smp_processor_id(). + + +``__init``/``__exit``/``__initdata`` +------------------------------------ + +Definite in ``include/linux/init.h`` + +Dopo l'avvio, il kernel libera una sezione speciale; le funzioni marcate +con ``__init`` e le strutture dati marcate con ``__initdata`` vengono +eliminate dopo il completamento dell'avvio: in modo simile i moduli eliminano +questa memoria dopo l'inizializzazione. ``__exit`` viene utilizzato per +dichiarare che una funzione verrà utilizzata solo in fase di rimozione: +la detta funzione verrà eliminata quando il file che la contiene non è +compilato come modulo. Guardate l'header file per informazioni. Da notare che +non ha senso avere una funzione marcata come ``__init`` e al tempo stesso +esportata ai moduli utilizzando :c:func:`EXPORT_SYMBOL()` o +:c:func:`EXPORT_SYMBOL_GPL()` - non funzionerà. + + +:c:func:`__initcall()`/:c:func:`module_init()` +---------------------------------------------- + +Definite in ``include/linux/init.h`` / ``include/linux/module.h`` + +Molte parti del kernel funzionano bene come moduli (componenti del kernel +caricabili dinamicamente). L'utilizzo delle macro :c:func:`module_init()` +e :c:func:`module_exit()` semplifica la scrittura di codice che può funzionare +sia come modulo, sia come parte del kernel, senza l'ausilio di #ifdef. + +La macro :c:func:`module_init()` definisce quale funzione dev'essere +chiamata quando il modulo viene inserito (se il file è stato compilato come +tale), o in fase di avvio : se il file non è stato compilato come modulo la +macro :c:func:`module_init()` diventa equivalente a :c:func:`__initcall()`, +la quale, tramite qualche magia del linker, s'assicura che la funzione venga +chiamata durante l'avvio. + +La funzione può ritornare un numero d'errore negativo per scatenare un +fallimento del caricamento (sfortunatamente, questo non ha effetto se il +modulo è compilato come parte integrante del kernel). Questa funzione è chiamata +in contesto utente con le interruzioni abilitate, quindi potrebbe dormire. + + +:c:func:`module_exit()` +----------------------- + + +Definita in ``include/linux/module.h`` + +Questa macro definisce la funzione che dev'essere chiamata al momento della +rimozione (o mai, nel caso in cui il file sia parte integrante del kernel). +Essa verrà chiamata solo quando il contatore d'uso del modulo raggiunge lo +zero. Questa funzione può anche dormire, ma non può fallire: tutto dev'essere +ripulito prima che la funzione ritorni. + +Da notare che questa macro è opzionale: se non presente, il modulo non sarà +removibile (a meno che non usiate 'rmmod -f' ). + + +:c:func:`try_module_get()`/:c:func:`module_put()` +------------------------------------------------- + +Definite in ``include/linux/module.h`` + +Queste funzioni maneggiano il contatore d'uso del modulo per proteggerlo dalla +rimozione (in aggiunta, un modulo non può essere rimosso se un altro modulo +utilizzo uno dei sui simboli esportati: vedere di seguito). Prima di eseguire +codice del modulo, dovreste chiamare :c:func:`try_module_get()` su quel modulo: +se fallisce significa che il modulo è stato rimosso e dovete agire come se +non fosse presente. Altrimenti, potete accedere al modulo in sicurezza, e +chiamare :c:func:`module_put()` quando avete finito. + +La maggior parte delle strutture registrabili hanno un campo owner +(proprietario), come nella struttura +:c:type:`struct file_operations `. +Impostate questo campo al valore della macro ``THIS_MODULE``. + + +Code d'attesa ``include/linux/wait.h`` +====================================== + +**[DORMONO]** + +Una coda d'attesa è usata per aspettare che qualcuno vi attivi quando una +certa condizione s'avvera. Per evitare corse critiche, devono essere usate +con cautela. Dichiarate una :c:type:`wait_queue_head_t`, e poi i processi +che vogliono attendere il verificarsi di quella condizione dichiareranno +una :c:type:`wait_queue_entry_t` facendo riferimento a loro stessi, poi +metteranno questa in coda. + +Dichiarazione +------------- + +Potere dichiarare una ``wait_queue_head_t`` utilizzando la macro +:c:func:`DECLARE_WAIT_QUEUE_HEAD()` oppure utilizzando la procedura +:c:func:`init_waitqueue_head()` nel vostro codice d'inizializzazione. + +Accodamento +----------- + +Mettersi in una coda d'attesa è piuttosto complesso, perché dovete +mettervi in coda prima di verificare la condizione. Esiste una macro +a questo scopo: :c:func:`wait_event_interruptible()` (``include/linux/wait.h``). +Il primo argomento è la testa della coda d'attesa, e il secondo è +un'espressione che dev'essere valutata; la macro ritorna 0 quando questa +espressione è vera, altrimenti ``-ERESTARTSYS`` se è stato ricevuto un segnale. +La versione :c:func:`wait_event()` ignora i segnali. + +Svegliare una procedura in coda +------------------------------- + +Chiamate :c:func:`wake_up()` (``include/linux/wait.h``); questa attiverà tutti +i processi in coda. Ad eccezione se uno di questi è impostato come +``TASK_EXCLUSIVE``, in questo caso i rimanenti non verranno svegliati. +Nello stesso header file esistono altre varianti di questa funzione. + +Operazioni atomiche +=================== + +Certe operazioni sono garantite come atomiche su tutte le piattaforme. +Il primo gruppo di operazioni utilizza :c:type:`atomic_t` +(``include/asm/atomic.h``); questo contiene un intero con segno (minimo 32bit), +e dovete utilizzare queste funzione per modificare o leggere variabili di tipo +:c:type:`atomic_t`. :c:func:`atomic_read()` e :c:func:`atomic_set()` leggono ed +impostano il contatore, :c:func:`atomic_add()`, :c:func:`atomic_sub()`, +:c:func:`atomic_inc()`, :c:func:`atomic_dec()`, e +:c:func:`atomic_dec_and_test()` (ritorna vero se raggiunge zero dopo essere +stata decrementata). + +Sì. Ritorna vero (ovvero != 0) se la variabile atomica è zero. + +Da notare che queste funzioni sono più lente rispetto alla normale aritmetica, +e quindi non dovrebbero essere usate a sproposito. + +Il secondo gruppo di operazioni atomiche sono definite in +``include/linux/bitops.h`` ed agiscono sui bit d'una variabile di tipo +``unsigned long``. Queste operazioni prendono come argomento un puntatore +alla variabile, e un numero di bit dove 0 è quello meno significativo. +:c:func:`set_bit()`, :c:func:`clear_bit()` e :c:func:`change_bit()` +impostano, cancellano, ed invertono il bit indicato. +:c:func:`test_and_set_bit()`, :c:func:`test_and_clear_bit()` e +:c:func:`test_and_change_bit()` fanno la stessa cosa, ad eccezione che +ritornano vero se il bit era impostato; queste sono particolarmente +utili quando si vuole impostare atomicamente dei flag. + +Con queste operazioni è possibile utilizzare indici di bit che eccedono +il valore ``BITS_PER_LONG``. Il comportamento è strano sulle piattaforme +big-endian quindi è meglio evitarlo. + +Simboli +======= + +All'interno del kernel, si seguono le normali regole del linker (ovvero, +a meno che un simbolo non venga dichiarato con visibilita limitata ad un +file con la parola chiave ``static``, esso può essere utilizzato in qualsiasi +parte del kernel). Nonostante ciò, per i moduli, esiste una tabella dei +simboli esportati che limita i punti di accesso al kernel. Anche i moduli +possono esportare simboli. + +:c:func:`EXPORT_SYMBOL()` +------------------------- + +Definita in ``include/linux/export.h`` + +Questo è il classico metodo per esportare un simbolo: i moduli caricati +dinamicamente potranno utilizzare normalmente il simbolo. + +:c:func:`EXPORT_SYMBOL_GPL()` +----------------------------- + +Definita in ``include/linux/export.h`` + +Essa è simile a :c:func:`EXPORT_SYMBOL()` ad eccezione del fatto che i +simboli esportati con :c:func:`EXPORT_SYMBOL_GPL()` possono essere +utilizzati solo dai moduli che hanno dichiarato una licenza compatibile +con la GPL attraverso :c:func:`MODULE_LICENSE()`. Questo implica che la +funzione esportata è considerata interna, e non una vera e propria interfaccia. +Alcuni manutentori e sviluppatori potrebbero comunque richiedere +:c:func:`EXPORT_SYMBOL_GPL()` quando si aggiungono nuove funzionalità o +interfacce. + +:c:func:`EXPORT_SYMBOL_NS()` +---------------------------- + +Definita in ``include/linux/export.h`` + +Questa è una variate di `EXPORT_SYMBOL()` che permette di specificare uno +spazio dei nomi. Lo spazio dei nomi è documentato in +Documentation/translations/it_IT/core-api/symbol-namespaces.rst. + +:c:func:`EXPORT_SYMBOL_NS_GPL()` +-------------------------------- + +Definita in ``include/linux/export.h`` + +Questa è una variate di `EXPORT_SYMBOL_GPL()` che permette di specificare uno +spazio dei nomi. Lo spazio dei nomi è documentato in +Documentation/translations/it_IT/core-api/symbol-namespaces.rst. + +Procedure e convenzioni +======================= + +Liste doppiamente concatenate ``include/linux/list.h`` +------------------------------------------------------ + +Un tempo negli header del kernel c'erano tre gruppi di funzioni per +le liste concatenate, ma questa è stata la vincente. Se non avete particolari +necessità per una semplice lista concatenata, allora questa è una buona scelta. + +In particolare, :c:func:`list_for_each_entry()` è utile. + +Convenzione dei valori di ritorno +--------------------------------- + +Per codice chiamato in contesto utente, è molto comune sfidare le convenzioni +C e ritornare 0 in caso di successo, ed un codice di errore negativo +(eg. ``-EFAULT``) nei casi fallimentari. Questo potrebbe essere controintuitivo +a prima vista, ma è abbastanza diffuso nel kernel. + +Utilizzate :c:func:`ERR_PTR()` (``include/linux/err.h``) per codificare +un numero d'errore negativo in un puntatore, e :c:func:`IS_ERR()` e +:c:func:`PTR_ERR()` per recuperarlo di nuovo: così si evita d'avere un +puntatore dedicato per il numero d'errore. Da brividi, ma in senso positivo. + +Rompere la compilazione +----------------------- + +Linus e gli altri sviluppatori a volte cambiano i nomi delle funzioni e +delle strutture nei kernel in sviluppo; questo non è solo per tenere +tutti sulle spine: questo riflette cambiamenti fondamentati (eg. la funzione +non può più essere chiamata con le funzioni attive, o fa controlli aggiuntivi, +o non fa più controlli che venivano fatti in precedenza). Solitamente a questo +s'accompagna un'adeguata e completa nota sulla lista di discussone +più adatta; cercate negli archivi. Solitamente eseguire una semplice +sostituzione su tutto un file rendere le cose **peggiori**. + +Inizializzazione dei campi d'una struttura +------------------------------------------ + +Il metodo preferito per l'inizializzazione delle strutture è quello +di utilizzare gli inizializzatori designati, come definiti nello +standard ISO C99, eg:: + + static struct block_device_operations opt_fops = { + .open = opt_open, + .release = opt_release, + .ioctl = opt_ioctl, + .check_media_change = opt_media_change, + }; + +Questo rende più facile la ricerca con grep, e rende più chiaro quale campo +viene impostato. Dovreste fare così perché si mostra meglio. + +Estensioni GNU +-------------- + +Le estensioni GNU sono esplicitamente permesse nel kernel Linux. Da notare +che alcune delle più complesse non sono ben supportate, per via dello scarso +sviluppo, ma le seguenti sono da considerarsi la norma (per maggiori dettagli, +leggete la sezione "C Extensions" nella pagina info di GCC - Sì, davvero +la pagina info, la pagina man è solo un breve riassunto delle cose nella +pagina info). + +- Funzioni inline + +- Istruzioni in espressioni (ie. il costrutto ({ and }) ). + +- Dichiarate attributi di una funzione / variabile / tipo + (__attribute__) + +- typeof + +- Array con lunghezza zero + +- Macro varargs + +- Aritmentica sui puntatori void + +- Inizializzatori non costanti + +- Istruzioni assembler (non al di fuori di 'arch/' e 'include/asm/') + +- Nomi delle funzioni come stringhe (__func__). + +- __builtin_constant_p() + +Siate sospettosi quando utilizzate long long nel kernel, il codice generato +da gcc è orribile ed anche peggio: le divisioni e le moltiplicazioni non +funzionano sulle piattaforme i386 perché le rispettive funzioni di runtime +di GCC non sono incluse nell'ambiente del kernel. + +C++ +--- + +Solitamente utilizzare il C++ nel kernel è una cattiva idea perché +il kernel non fornisce il necessario ambiente di runtime e gli header file +non sono stati verificati. Rimane comunque possibile, ma non consigliato. +Se davvero volete usarlo, almeno evitate le eccezioni. + +NUMif +----- + +Viene generalmente considerato più pulito l'uso delle macro negli header file +(o all'inizio dei file .c) per astrarre funzioni piuttosto che utlizzare +l'istruzione di pre-processore \`#if' all'interno del codice sorgente. + +Mettere le vostre cose nel kernel +================================= + +Al fine d'avere le vostre cose in ordine per l'inclusione ufficiale, o +anche per avere patch pulite, c'è del lavoro amministrativo da fare: + +- Trovare chi è responsabile del codice che state modificando. Guardare in cima + ai file sorgenti, all'interno del file ``MAINTAINERS``, ed alla fine + di tutti nel file ``CREDITS``. Dovreste coordinarvi con queste persone + per evitare di duplicare gli sforzi, o provare qualcosa che è già stato + rigettato. + + Assicuratevi di mettere il vostro nome ed indirizzo email in cima a + tutti i file che create o che maneggiate significativamente. Questo è + il primo posto dove le persone guarderanno quando troveranno un baco, + o quando **loro** vorranno fare una modifica. + +- Solitamente vorrete un'opzione di configurazione per la vostra modifica + al kernel. Modificate ``Kconfig`` nella cartella giusta. Il linguaggio + Config è facile con copia ed incolla, e c'è una completa documentazione + nel file ``Documentation/kbuild/kconfig-language.rst``. + + Nella descrizione della vostra opzione, assicuratevi di parlare sia agli + utenti esperti sia agli utente che non sanno nulla del vostro lavoro. + Menzionate qui le incompatibilità ed i problemi. Chiaramente la + descrizione deve terminare con “if in doubt, say N” (se siete in dubbio, + dite N) (oppure, occasionalmente, \`Y'); questo è per le persone che non + hanno idea di che cosa voi stiate parlando. + +- Modificate il file ``Makefile``: le variabili CONFIG sono esportate qui, + quindi potete solitamente aggiungere una riga come la seguete + "obj-$(CONFIG_xxx) += xxx.o". La sintassi è documentata nel file + ``Documentation/kbuild/makefiles.rst``. + +- Aggiungete voi stessi in ``CREDITS`` se credete di aver fatto qualcosa di + notevole, solitamente qualcosa che supera il singolo file (comunque il vostro + nome dovrebbe essere all'inizio dei file sorgenti). ``MAINTAINERS`` significa + che volete essere consultati quando vengono fatte delle modifiche ad un + sottosistema, e quando ci sono dei bachi; questo implica molto di più di un + semplice impegno su una parte del codice. + +- Infine, non dimenticatevi di leggere + ``Documentation/process/submitting-patches.rst``. + +Trucchetti del kernel +===================== + +Dopo una rapida occhiata al codice, questi sono i preferiti. Sentitevi liberi +di aggiungerne altri. + +``arch/x86/include/asm/delay.h``:: + + #define ndelay(n) (__builtin_constant_p(n) ? \ + ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \ + __ndelay(n)) + + +``include/linux/fs.h``:: + + /* + * Kernel pointers have redundant information, so we can use a + * scheme where we can return either an error code or a dentry + * pointer with the same return value. + * + * This should be a per-architecture thing, to allow different + * error and pointer decisions. + */ + #define ERR_PTR(err) ((void *)((long)(err))) + #define PTR_ERR(ptr) ((long)(ptr)) + #define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) + +``arch/x86/include/asm/uaccess_32.h:``:: + + #define copy_to_user(to,from,n) \ + (__builtin_constant_p(n) ? \ + __constant_copy_to_user((to),(from),(n)) : \ + __generic_copy_to_user((to),(from),(n))) + + +``arch/sparc/kernel/head.S:``:: + + /* + * Sun people can't spell worth damn. "compatability" indeed. + * At least we *know* we can't spell, and use a spell-checker. + */ + + /* Uh, actually Linus it is I who cannot spell. Too much murky + * Sparc assembly will do this to ya. + */ + C_LABEL(cputypvar): + .asciz "compatibility" + + /* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */ + .align 4 + C_LABEL(cputypvar_sun4m): + .asciz "compatible" + + +``arch/sparc/lib/checksum.S:``:: + + /* Sun, you just can't beat me, you just can't. Stop trying, + * give up. I'm serious, I am going to kick the living shit + * out of you, game over, lights out. + */ + + +Ringraziamenti +============== + +Ringrazio Andi Kleen per le sue idee, le risposte alle mie domande, +le correzioni dei miei errori, l'aggiunta di contenuti, eccetera. +Philipp Rumpf per l'ortografia e per aver reso più chiaro il testo, e +per alcuni eccellenti punti tutt'altro che ovvi. Werner Almesberger +per avermi fornito un ottimo riassunto di :c:func:`disable_irq()`, +e Jes Sorensen e Andrea Arcangeli per le precisazioni. Michael Elizabeth +Chastain per aver verificato ed aggiunto la sezione configurazione. +Telsa Gwynne per avermi insegnato DocBook. diff --git a/Documentation/translations/it_IT/kernel-hacking/index.rst b/Documentation/translations/it_IT/kernel-hacking/index.rst new file mode 100644 index 000000000..50228380b --- /dev/null +++ b/Documentation/translations/it_IT/kernel-hacking/index.rst @@ -0,0 +1,16 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/kernel-hacking/index.rst ` +:Translator: Federico Vaga + +.. _it_kernel_hacking: + +============================ +Guida all'hacking del kernel +============================ + +.. toctree:: + :maxdepth: 2 + + hacking + locking diff --git a/Documentation/translations/it_IT/kernel-hacking/locking.rst b/Documentation/translations/it_IT/kernel-hacking/locking.rst new file mode 100644 index 000000000..51af37f2d --- /dev/null +++ b/Documentation/translations/it_IT/kernel-hacking/locking.rst @@ -0,0 +1,1495 @@ +.. include:: ../disclaimer-ita.rst + +.. c:namespace:: it_IT + +:Original: :ref:`Documentation/kernel-hacking/locking.rst ` +:Translator: Federico Vaga + +.. _it_kernel_hacking_lock: + +========================================== +L'inaffidabile guida alla sincronizzazione +========================================== + +:Author: Rusty Russell + +Introduzione +============ + +Benvenuto, alla notevole ed inaffidabile guida ai problemi di sincronizzazione +(locking) nel kernel. Questo documento descrive il sistema di sincronizzazione +nel kernel Linux 2.6. + +Dato il largo utilizzo del multi-threading e della prelazione nel kernel +Linux, chiunque voglia dilettarsi col kernel deve conoscere i concetti +fondamentali della concorrenza e della sincronizzazione nei sistemi +multi-processore. + +Il problema con la concorrenza +============================== + +(Saltatelo se sapete già cos'è una corsa critica). + +In un normale programma, potete incrementare un contatore nel seguente modo: + +:: + + contatore++; + +Questo è quello che vi aspettereste che accada sempre: + + +.. table:: Risultati attesi + + +------------------------------------+------------------------------------+ + | Istanza 1 | Istanza 2 | + +====================================+====================================+ + | leggi contatore (5) | | + +------------------------------------+------------------------------------+ + | aggiungi 1 (6) | | + +------------------------------------+------------------------------------+ + | scrivi contatore (6) | | + +------------------------------------+------------------------------------+ + | | leggi contatore (6) | + +------------------------------------+------------------------------------+ + | | aggiungi 1 (7) | + +------------------------------------+------------------------------------+ + | | scrivi contatore (7) | + +------------------------------------+------------------------------------+ + +Questo è quello che potrebbe succedere in realtà: + +.. table:: Possibile risultato + + +------------------------------------+------------------------------------+ + | Istanza 1 | Istanza 2 | + +====================================+====================================+ + | leggi contatore (5) | | + +------------------------------------+------------------------------------+ + | | leggi contatore (5) | + +------------------------------------+------------------------------------+ + | aggiungi 1 (6) | | + +------------------------------------+------------------------------------+ + | | aggiungi 1 (6) | + +------------------------------------+------------------------------------+ + | scrivi contatore (6) | | + +------------------------------------+------------------------------------+ + | | scrivi contatore (6) | + +------------------------------------+------------------------------------+ + + +Corse critiche e sezioni critiche +--------------------------------- + +Questa sovrapposizione, ovvero quando un risultato dipende dal tempo che +intercorre fra processi diversi, è chiamata corsa critica. La porzione +di codice che contiene questo problema è chiamata sezione critica. +In particolar modo da quando Linux ha incominciato a girare su +macchine multi-processore, le sezioni critiche sono diventate uno dei +maggiori problemi di progettazione ed implementazione del kernel. + +La prelazione può sortire gli stessi effetti, anche se c'è una sola CPU: +interrompendo un processo nella sua sezione critica otterremo comunque +la stessa corsa critica. In questo caso, il thread che si avvicenda +nell'esecuzione potrebbe eseguire anch'esso la sezione critica. + +La soluzione è quella di riconoscere quando avvengono questi accessi +simultanei, ed utilizzare i *lock* per accertarsi che solo un'istanza +per volta possa entrare nella sezione critica. Il kernel offre delle buone +funzioni a questo scopo. E poi ci sono quelle meno buone, ma farò finta +che non esistano. + +Sincronizzazione nel kernel Linux +================================= + +Se dovessi darvi un suggerimento sulla sincronizzazione: **mantenetela +semplice**. + +Siate riluttanti nell'introduzione di nuovi *lock*. + +I due principali tipi di *lock* nel kernel: spinlock e mutex +------------------------------------------------------------ + +Ci sono due tipi principali di *lock* nel kernel. Il tipo fondamentale è lo +spinlock (``include/asm/spinlock.h``), un semplice *lock* che può essere +trattenuto solo da un processo: se non si può trattenere lo spinlock, allora +rimane in attesa attiva (in inglese *spinning*) finché non ci riesce. +Gli spinlock sono molto piccoli e rapidi, possono essere utilizzati ovunque. + +Il secondo tipo è il mutex (``include/linux/mutex.h``): è come uno spinlock, +ma potreste bloccarvi trattenendolo. Se non potete trattenere un mutex +il vostro processo si auto-sospenderà; verrà riattivato quando il mutex +verrà rilasciato. Questo significa che il processore potrà occuparsi d'altro +mentre il vostro processo è in attesa. Esistono molti casi in cui non potete +permettervi di sospendere un processo (vedere +`Quali funzioni possono essere chiamate in modo sicuro dalle interruzioni?`_) +e quindi dovrete utilizzare gli spinlock. + +Nessuno di questi *lock* è ricorsivo: vedere +`Stallo: semplice ed avanzato`_ + +I *lock* e i kernel per sistemi monoprocessore +---------------------------------------------- + +Per i kernel compilati senza ``CONFIG_SMP`` e senza ``CONFIG_PREEMPT`` +gli spinlock non esistono. Questa è un'ottima scelta di progettazione: +quando nessun altro processo può essere eseguito in simultanea, allora +non c'è la necessità di avere un *lock*. + +Se il kernel è compilato senza ``CONFIG_SMP`` ma con ``CONFIG_PREEMPT``, +allora gli spinlock disabilitano la prelazione; questo è sufficiente a +prevenire le corse critiche. Nella maggior parte dei casi, possiamo considerare +la prelazione equivalente ad un sistema multi-processore senza preoccuparci +di trattarla indipendentemente. + +Dovreste verificare sempre la sincronizzazione con le opzioni ``CONFIG_SMP`` e +``CONFIG_PREEMPT`` abilitate, anche quando non avete un sistema +multi-processore, questo vi permetterà di identificare alcuni problemi +di sincronizzazione. + +Come vedremo di seguito, i mutex continuano ad esistere perché sono necessari +per la sincronizzazione fra processi in contesto utente. + +Sincronizzazione in contesto utente +----------------------------------- + +Se avete una struttura dati che verrà utilizzata solo dal contesto utente, +allora, per proteggerla, potete utilizzare un semplice mutex +(``include/linux/mutex.h``). Questo è il caso più semplice: inizializzate il +mutex; invocate mutex_lock_interruptible() per trattenerlo e +mutex_unlock() per rilasciarlo. C'è anche mutex_lock() +ma questa dovrebbe essere evitata perché non ritorna in caso di segnali. + +Per esempio: ``net/netfilter/nf_sockopt.c`` permette la registrazione +di nuove chiamate per setsockopt() e getsockopt() +usando la funzione nf_register_sockopt(). La registrazione e +la rimozione vengono eseguite solamente quando il modulo viene caricato +o scaricato (e durante l'avvio del sistema, qui non abbiamo concorrenza), +e la lista delle funzioni registrate viene consultata solamente quando +setsockopt() o getsockopt() sono sconosciute al sistema. +In questo caso ``nf_sockopt_mutex`` è perfetto allo scopo, in particolar modo +visto che setsockopt e getsockopt potrebbero dormire. + +Sincronizzazione fra il contesto utente e i softirq +--------------------------------------------------- + +Se un softirq condivide dati col contesto utente, avete due problemi. +Primo, il contesto utente corrente potrebbe essere interroto da un softirq, +e secondo, la sezione critica potrebbe essere eseguita da un altro +processore. Questo è quando spin_lock_bh() +(``include/linux/spinlock.h``) viene utilizzato. Questo disabilita i softirq +sul processore e trattiene il *lock*. Invece, spin_unlock_bh() fa +l'opposto. (Il suffisso '_bh' è un residuo storico che fa riferimento al +"Bottom Halves", il vecchio nome delle interruzioni software. In un mondo +perfetto questa funzione si chiamerebbe 'spin_lock_softirq()'). + +Da notare che in questo caso potete utilizzare anche spin_lock_irq() +o spin_lock_irqsave(), queste fermano anche le interruzioni hardware: +vedere `Contesto di interruzione hardware`_. + +Questo funziona alla perfezione anche sui sistemi monoprocessore: gli spinlock +svaniscono e questa macro diventa semplicemente local_bh_disable() +(``include/linux/interrupt.h``), la quale impedisce ai softirq d'essere +eseguiti. + +Sincronizzazione fra contesto utente e i tasklet +------------------------------------------------ + +Questo caso è uguale al precedente, un tasklet viene eseguito da un softirq. + +Sincronizzazione fra contesto utente e i timer +---------------------------------------------- + +Anche questo caso è uguale al precedente, un timer viene eseguito da un +softirq. +Dal punto di vista della sincronizzazione, tasklet e timer sono identici. + +Sincronizzazione fra tasklet e timer +------------------------------------ + +Qualche volta un tasklet od un timer potrebbero condividere i dati con +un altro tasklet o timer + +Lo stesso tasklet/timer +~~~~~~~~~~~~~~~~~~~~~~~ + +Dato che un tasklet non viene mai eseguito contemporaneamente su due +processori, non dovete preoccuparvi che sia rientrante (ovvero eseguito +più volte in contemporanea), perfino su sistemi multi-processore. + +Differenti tasklet/timer +~~~~~~~~~~~~~~~~~~~~~~~~ + +Se un altro tasklet/timer vuole condividere dati col vostro tasklet o timer, +allora avrete bisogno entrambe di spin_lock() e +spin_unlock(). Qui spin_lock_bh() è inutile, siete già +in un tasklet ed avete la garanzia che nessun altro verrà eseguito sullo +stesso processore. + +Sincronizzazione fra softirq +---------------------------- + +Spesso un softirq potrebbe condividere dati con se stesso o un tasklet/timer. + +Lo stesso softirq +~~~~~~~~~~~~~~~~~ + +Lo stesso softirq può essere eseguito su un diverso processore: allo scopo +di migliorare le prestazioni potete utilizzare dati riservati ad ogni +processore (vedere `Dati per processore`_). Se siete arrivati +fino a questo punto nell'uso dei softirq, probabilmente tenete alla scalabilità +delle prestazioni abbastanza da giustificarne la complessità aggiuntiva. + +Dovete utilizzare spin_lock() e spin_unlock() per +proteggere i dati condivisi. + +Diversi Softirqs +~~~~~~~~~~~~~~~~ + +Dovete utilizzare spin_lock() e spin_unlock() per +proteggere i dati condivisi, che siano timer, tasklet, diversi softirq o +lo stesso o altri softirq: uno qualsiasi di essi potrebbe essere in esecuzione +su un diverso processore. + +.. _`it_hardirq-context`: + +Contesto di interruzione hardware +================================= + +Solitamente le interruzioni hardware comunicano con un tasklet o un softirq. +Spesso questo si traduce nel mettere in coda qualcosa da fare che verrà +preso in carico da un softirq. + +Sincronizzazione fra interruzioni hardware e softirq/tasklet +------------------------------------------------------------ + +Se un gestore di interruzioni hardware condivide dati con un softirq, allora +avrete due preoccupazioni. Primo, il softirq può essere interrotto da +un'interruzione hardware, e secondo, la sezione critica potrebbe essere +eseguita da un'interruzione hardware su un processore diverso. Questo è il caso +dove spin_lock_irq() viene utilizzato. Disabilita le interruzioni +sul processore che l'esegue, poi trattiene il lock. spin_unlock_irq() +fa l'opposto. + +Il gestore d'interruzione hardware non ha bisogno di usare spin_lock_irq() +perché i softirq non possono essere eseguiti quando il gestore d'interruzione +hardware è in esecuzione: per questo si può usare spin_lock(), che è un po' +più veloce. L'unica eccezione è quando un altro gestore d'interruzioni +hardware utilizza lo stesso *lock*: spin_lock_irq() impedirà a questo +secondo gestore di interrompere quello in esecuzione. + +Questo funziona alla perfezione anche sui sistemi monoprocessore: gli spinlock +svaniscono e questa macro diventa semplicemente local_irq_disable() +(``include/asm/smp.h``), la quale impedisce a softirq/tasklet/BH d'essere +eseguiti. + +spin_lock_irqsave() (``include/linux/spinlock.h``) è una variante che +salva lo stato delle interruzioni in una variabile, questa verrà poi passata +a spin_unlock_irqrestore(). Questo significa che lo stesso codice +potrà essere utilizzato in un'interruzione hardware (dove le interruzioni sono +già disabilitate) e in un softirq (dove la disabilitazione delle interruzioni +è richiesta). + +Da notare che i softirq (e quindi tasklet e timer) sono eseguiti al ritorno +da un'interruzione hardware, quindi spin_lock_irq() interrompe +anche questi. Tenuto conto di questo si può dire che +spin_lock_irqsave() è la funzione di sincronizzazione più generica +e potente. + +Sincronizzazione fra due gestori d'interruzioni hardware +-------------------------------------------------------- + +Condividere dati fra due gestori di interruzione hardware è molto raro, ma se +succede, dovreste usare spin_lock_irqsave(): è una specificità +dell'architettura il fatto che tutte le interruzioni vengano interrotte +quando si eseguono di gestori di interruzioni. + +Bigino della sincronizzazione +============================= + +Pete Zaitcev ci offre il seguente riassunto: + +- Se siete in un contesto utente (una qualsiasi chiamata di sistema) + e volete sincronizzarvi con altri processi, usate i mutex. Potete trattenere + il mutex e dormire (``copy_from_user(`` o ``kmalloc(x,GFP_KERNEL)``). + +- Altrimenti (== i dati possono essere manipolati da un'interruzione) usate + spin_lock_irqsave() e spin_unlock_irqrestore(). + +- Evitate di trattenere uno spinlock per più di 5 righe di codice incluse + le chiamate a funzione (ad eccezione di quell per l'accesso come + readb()). + +Tabella dei requisiti minimi +---------------------------- + +La tabella seguente illustra i requisiti **minimi** per la sincronizzazione fra +diversi contesti. In alcuni casi, lo stesso contesto può essere eseguito solo +da un processore per volta, quindi non ci sono requisiti per la +sincronizzazione (per esempio, un thread può essere eseguito solo su un +processore alla volta, ma se deve condividere dati con un altro thread, allora +la sincronizzazione è necessaria). + +Ricordatevi il suggerimento qui sopra: potete sempre usare +spin_lock_irqsave(), che è un sovrainsieme di tutte le altre funzioni +per spinlock. + +============== ============= ============= ========= ========= ========= ========= ======= ======= ============== ============== +. IRQ Handler A IRQ Handler B Softirq A Softirq B Tasklet A Tasklet B Timer A Timer B User Context A User Context B +============== ============= ============= ========= ========= ========= ========= ======= ======= ============== ============== +IRQ Handler A None +IRQ Handler B SLIS None +Softirq A SLI SLI SL +Softirq B SLI SLI SL SL +Tasklet A SLI SLI SL SL None +Tasklet B SLI SLI SL SL SL None +Timer A SLI SLI SL SL SL SL None +Timer B SLI SLI SL SL SL SL SL None +User Context A SLI SLI SLBH SLBH SLBH SLBH SLBH SLBH None +User Context B SLI SLI SLBH SLBH SLBH SLBH SLBH SLBH MLI None +============== ============= ============= ========= ========= ========= ========= ======= ======= ============== ============== + +Table: Tabella dei requisiti per la sincronizzazione + ++--------+----------------------------+ +| SLIS | spin_lock_irqsave | ++--------+----------------------------+ +| SLI | spin_lock_irq | ++--------+----------------------------+ +| SL | spin_lock | ++--------+----------------------------+ +| SLBH | spin_lock_bh | ++--------+----------------------------+ +| MLI | mutex_lock_interruptible | ++--------+----------------------------+ + +Table: Legenda per la tabella dei requisiti per la sincronizzazione + +Le funzioni *trylock* +===================== + +Ci sono funzioni che provano a trattenere un *lock* solo una volta e +ritornano immediatamente comunicato il successo od il fallimento +dell'operazione. Posso essere usate quando non serve accedere ai dati +protetti dal *lock* quando qualche altro thread lo sta già facendo +trattenendo il *lock*. Potrete acquisire il *lock* più tardi se vi +serve accedere ai dati protetti da questo *lock*. + +La funzione spin_trylock() non ritenta di acquisire il *lock*, +se ci riesce al primo colpo ritorna un valore diverso da zero, altrimenti +se fallisce ritorna 0. Questa funzione può essere utilizzata in un qualunque +contesto, ma come spin_lock(): dovete disabilitare i contesti che +potrebbero interrompervi e quindi trattenere lo spinlock. + +La funzione mutex_trylock() invece di sospendere il vostro processo +ritorna un valore diverso da zero se è possibile trattenere il lock al primo +colpo, altrimenti se fallisce ritorna 0. Nonostante non dorma, questa funzione +non può essere usata in modo sicuro in contesti di interruzione hardware o +software. + +Esempi più comuni +================= + +Guardiamo un semplice esempio: una memoria che associa nomi a numeri. +La memoria tiene traccia di quanto spesso viene utilizzato ogni oggetto; +quando è piena, l'oggetto meno usato viene eliminato. + +Tutto in contesto utente +------------------------ + +Nel primo esempio, supponiamo che tutte le operazioni avvengano in contesto +utente (in soldoni, da una chiamata di sistema), quindi possiamo dormire. +Questo significa che possiamo usare i mutex per proteggere la nostra memoria +e tutti gli oggetti che contiene. Ecco il codice:: + + #include + #include + #include + #include + #include + + struct object + { + struct list_head list; + int id; + char name[32]; + int popularity; + }; + + /* Protects the cache, cache_num, and the objects within it */ + static DEFINE_MUTEX(cache_lock); + static LIST_HEAD(cache); + static unsigned int cache_num = 0; + #define MAX_CACHE_SIZE 10 + + /* Must be holding cache_lock */ + static struct object *__cache_find(int id) + { + struct object *i; + + list_for_each_entry(i, &cache, list) + if (i->id == id) { + i->popularity++; + return i; + } + return NULL; + } + + /* Must be holding cache_lock */ + static void __cache_delete(struct object *obj) + { + BUG_ON(!obj); + list_del(&obj->list); + kfree(obj); + cache_num--; + } + + /* Must be holding cache_lock */ + static void __cache_add(struct object *obj) + { + list_add(&obj->list, &cache); + if (++cache_num > MAX_CACHE_SIZE) { + struct object *i, *outcast = NULL; + list_for_each_entry(i, &cache, list) { + if (!outcast || i->popularity < outcast->popularity) + outcast = i; + } + __cache_delete(outcast); + } + } + + int cache_add(int id, const char *name) + { + struct object *obj; + + if ((obj = kmalloc(sizeof(*obj), GFP_KERNEL)) == NULL) + return -ENOMEM; + + strscpy(obj->name, name, sizeof(obj->name)); + obj->id = id; + obj->popularity = 0; + + mutex_lock(&cache_lock); + __cache_add(obj); + mutex_unlock(&cache_lock); + return 0; + } + + void cache_delete(int id) + { + mutex_lock(&cache_lock); + __cache_delete(__cache_find(id)); + mutex_unlock(&cache_lock); + } + + int cache_find(int id, char *name) + { + struct object *obj; + int ret = -ENOENT; + + mutex_lock(&cache_lock); + obj = __cache_find(id); + if (obj) { + ret = 0; + strcpy(name, obj->name); + } + mutex_unlock(&cache_lock); + return ret; + } + +Da notare che ci assicuriamo sempre di trattenere cache_lock quando +aggiungiamo, rimuoviamo od ispezioniamo la memoria: sia la struttura +della memoria che il suo contenuto sono protetti dal *lock*. Questo +caso è semplice dato che copiamo i dati dall'utente e non permettiamo +mai loro di accedere direttamente agli oggetti. + +C'è una piccola ottimizzazione qui: nella funzione cache_add() +impostiamo i campi dell'oggetto prima di acquisire il *lock*. Questo è +sicuro perché nessun altro potrà accedervi finché non lo inseriremo +nella memoria. + +Accesso dal contesto utente +--------------------------- + +Ora consideriamo il caso in cui cache_find() può essere invocata +dal contesto d'interruzione: sia hardware che software. Un esempio potrebbe +essere un timer che elimina oggetti dalla memoria. + +Qui di seguito troverete la modifica nel formato *patch*: le righe ``-`` +sono quelle rimosse, mentre quelle ``+`` sono quelle aggiunte. + +:: + + --- cache.c.usercontext 2003-12-09 13:58:54.000000000 +1100 + +++ cache.c.interrupt 2003-12-09 14:07:49.000000000 +1100 + @@ -12,7 +12,7 @@ + int popularity; + }; + + -static DEFINE_MUTEX(cache_lock); + +static DEFINE_SPINLOCK(cache_lock); + static LIST_HEAD(cache); + static unsigned int cache_num = 0; + #define MAX_CACHE_SIZE 10 + @@ -55,6 +55,7 @@ + int cache_add(int id, const char *name) + { + struct object *obj; + + unsigned long flags; + + if ((obj = kmalloc(sizeof(*obj), GFP_KERNEL)) == NULL) + return -ENOMEM; + @@ -63,30 +64,33 @@ + obj->id = id; + obj->popularity = 0; + + - mutex_lock(&cache_lock); + + spin_lock_irqsave(&cache_lock, flags); + __cache_add(obj); + - mutex_unlock(&cache_lock); + + spin_unlock_irqrestore(&cache_lock, flags); + return 0; + } + + void cache_delete(int id) + { + - mutex_lock(&cache_lock); + + unsigned long flags; + + + + spin_lock_irqsave(&cache_lock, flags); + __cache_delete(__cache_find(id)); + - mutex_unlock(&cache_lock); + + spin_unlock_irqrestore(&cache_lock, flags); + } + + int cache_find(int id, char *name) + { + struct object *obj; + int ret = -ENOENT; + + unsigned long flags; + + - mutex_lock(&cache_lock); + + spin_lock_irqsave(&cache_lock, flags); + obj = __cache_find(id); + if (obj) { + ret = 0; + strcpy(name, obj->name); + } + - mutex_unlock(&cache_lock); + + spin_unlock_irqrestore(&cache_lock, flags); + return ret; + } + +Da notare che spin_lock_irqsave() disabiliterà le interruzioni +se erano attive, altrimenti non farà niente (quando siamo già in un contesto +d'interruzione); dunque queste funzioni possono essere chiamante in +sicurezza da qualsiasi contesto. + +Sfortunatamente, cache_add() invoca kmalloc() con +l'opzione ``GFP_KERNEL`` che è permessa solo in contesto utente. Ho supposto +che cache_add() venga chiamata dal contesto utente, altrimenti +questa opzione deve diventare un parametro di cache_add(). + +Esporre gli oggetti al di fuori del file +---------------------------------------- + +Se i vostri oggetti contengono più informazioni, potrebbe non essere +sufficiente copiare i dati avanti e indietro: per esempio, altre parti del +codice potrebbero avere un puntatore a questi oggetti piuttosto che cercarli +ogni volta. Questo introduce due problemi. + +Il primo problema è che utilizziamo ``cache_lock`` per proteggere gli oggetti: +dobbiamo renderlo dinamico così che il resto del codice possa usarlo. Questo +rende la sincronizzazione più complicata dato che non avviene più in un unico +posto. + +Il secondo problema è il problema del ciclo di vita: se un'altra struttura +mantiene un puntatore ad un oggetto, presumibilmente si aspetta che questo +puntatore rimanga valido. Sfortunatamente, questo è garantito solo mentre +si trattiene il *lock*, altrimenti qualcuno potrebbe chiamare +cache_delete() o peggio, aggiungere un oggetto che riutilizza lo +stesso indirizzo. + +Dato che c'è un solo *lock*, non potete trattenerlo a vita: altrimenti +nessun altro potrà eseguire il proprio lavoro. + +La soluzione a questo problema è l'uso di un contatore di riferimenti: +chiunque punti ad un oggetto deve incrementare il contatore, e decrementarlo +quando il puntatore non viene più usato. Quando il contatore raggiunge lo zero +significa che non è più usato e l'oggetto può essere rimosso. + +Ecco il codice:: + + --- cache.c.interrupt 2003-12-09 14:25:43.000000000 +1100 + +++ cache.c.refcnt 2003-12-09 14:33:05.000000000 +1100 + @@ -7,6 +7,7 @@ + struct object + { + struct list_head list; + + unsigned int refcnt; + int id; + char name[32]; + int popularity; + @@ -17,6 +18,35 @@ + static unsigned int cache_num = 0; + #define MAX_CACHE_SIZE 10 + + +static void __object_put(struct object *obj) + +{ + + if (--obj->refcnt == 0) + + kfree(obj); + +} + + + +static void __object_get(struct object *obj) + +{ + + obj->refcnt++; + +} + + + +void object_put(struct object *obj) + +{ + + unsigned long flags; + + + + spin_lock_irqsave(&cache_lock, flags); + + __object_put(obj); + + spin_unlock_irqrestore(&cache_lock, flags); + +} + + + +void object_get(struct object *obj) + +{ + + unsigned long flags; + + + + spin_lock_irqsave(&cache_lock, flags); + + __object_get(obj); + + spin_unlock_irqrestore(&cache_lock, flags); + +} + + + /* Must be holding cache_lock */ + static struct object *__cache_find(int id) + { + @@ -35,6 +65,7 @@ + { + BUG_ON(!obj); + list_del(&obj->list); + + __object_put(obj); + cache_num--; + } + + @@ -63,6 +94,7 @@ + strscpy(obj->name, name, sizeof(obj->name)); + obj->id = id; + obj->popularity = 0; + + obj->refcnt = 1; /* The cache holds a reference */ + + spin_lock_irqsave(&cache_lock, flags); + __cache_add(obj); + @@ -79,18 +111,15 @@ + spin_unlock_irqrestore(&cache_lock, flags); + } + + -int cache_find(int id, char *name) + +struct object *cache_find(int id) + { + struct object *obj; + - int ret = -ENOENT; + unsigned long flags; + + spin_lock_irqsave(&cache_lock, flags); + obj = __cache_find(id); + - if (obj) { + - ret = 0; + - strcpy(name, obj->name); + - } + + if (obj) + + __object_get(obj); + spin_unlock_irqrestore(&cache_lock, flags); + - return ret; + + return obj; + } + +Abbiamo incapsulato il contatore di riferimenti nelle tipiche funzioni +di 'get' e 'put'. Ora possiamo ritornare l'oggetto da cache_find() +col vantaggio che l'utente può dormire trattenendo l'oggetto (per esempio, +copy_to_user() per copiare il nome verso lo spazio utente). + +Un altro punto da notare è che ho detto che il contatore dovrebbe incrementarsi +per ogni puntatore ad un oggetto: quindi il contatore di riferimenti è 1 +quando l'oggetto viene inserito nella memoria. In altre versione il framework +non trattiene un riferimento per se, ma diventa più complicato. + +Usare operazioni atomiche per il contatore di riferimenti +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In sostanza, :c:type:`atomic_t` viene usato come contatore di riferimenti. +Ci sono un certo numbero di operazioni atomiche definite +in ``include/asm/atomic.h``: queste sono garantite come atomiche su qualsiasi +processore del sistema, quindi non sono necessari i *lock*. In questo caso è +più semplice rispetto all'uso degli spinlock, benché l'uso degli spinlock +sia più elegante per casi non banali. Le funzioni atomic_inc() e +atomic_dec_and_test() vengono usate al posto dei tipici operatori di +incremento e decremento, e i *lock* non sono più necessari per proteggere il +contatore stesso. + +:: + + --- cache.c.refcnt 2003-12-09 15:00:35.000000000 +1100 + +++ cache.c.refcnt-atomic 2003-12-11 15:49:42.000000000 +1100 + @@ -7,7 +7,7 @@ + struct object + { + struct list_head list; + - unsigned int refcnt; + + atomic_t refcnt; + int id; + char name[32]; + int popularity; + @@ -18,33 +18,15 @@ + static unsigned int cache_num = 0; + #define MAX_CACHE_SIZE 10 + + -static void __object_put(struct object *obj) + -{ + - if (--obj->refcnt == 0) + - kfree(obj); + -} + - + -static void __object_get(struct object *obj) + -{ + - obj->refcnt++; + -} + - + void object_put(struct object *obj) + { + - unsigned long flags; + - + - spin_lock_irqsave(&cache_lock, flags); + - __object_put(obj); + - spin_unlock_irqrestore(&cache_lock, flags); + + if (atomic_dec_and_test(&obj->refcnt)) + + kfree(obj); + } + + void object_get(struct object *obj) + { + - unsigned long flags; + - + - spin_lock_irqsave(&cache_lock, flags); + - __object_get(obj); + - spin_unlock_irqrestore(&cache_lock, flags); + + atomic_inc(&obj->refcnt); + } + + /* Must be holding cache_lock */ + @@ -65,7 +47,7 @@ + { + BUG_ON(!obj); + list_del(&obj->list); + - __object_put(obj); + + object_put(obj); + cache_num--; + } + + @@ -94,7 +76,7 @@ + strscpy(obj->name, name, sizeof(obj->name)); + obj->id = id; + obj->popularity = 0; + - obj->refcnt = 1; /* The cache holds a reference */ + + atomic_set(&obj->refcnt, 1); /* The cache holds a reference */ + + spin_lock_irqsave(&cache_lock, flags); + __cache_add(obj); + @@ -119,7 +101,7 @@ + spin_lock_irqsave(&cache_lock, flags); + obj = __cache_find(id); + if (obj) + - __object_get(obj); + + object_get(obj); + spin_unlock_irqrestore(&cache_lock, flags); + return obj; + } + +Proteggere l'oggetto stesso +--------------------------- + +In questo esempio, assumiamo che gli oggetti (ad eccezione del contatore +di riferimenti) non cambino mai dopo la loro creazione. Se vogliamo permettere +al nome di cambiare abbiamo tre possibilità: + +- Si può togliere static da ``cache_lock`` e dire agli utenti che devono + trattenere il *lock* prima di modificare il nome di un oggetto. + +- Si può fornire una funzione cache_obj_rename() che prende il + *lock* e cambia il nome per conto del chiamante; si dirà poi agli utenti + di usare questa funzione. + +- Si può decidere che ``cache_lock`` protegge solo la memoria stessa, ed + un altro *lock* è necessario per la protezione del nome. + +Teoricamente, possiamo avere un *lock* per ogni campo e per ogni oggetto. +In pratica, le varianti più comuni sono: + +- un *lock* che protegge l'infrastruttura (la lista ``cache`` di questo + esempio) e gli oggetti. Questo è quello che abbiamo fatto finora. + +- un *lock* che protegge l'infrastruttura (inclusi i puntatori alla lista + negli oggetti), e un *lock* nell'oggetto per proteggere il resto + dell'oggetto stesso. + +- *lock* multipli per proteggere l'infrastruttura (per esempio un *lock* + per ogni lista), possibilmente con un *lock* per oggetto. + +Qui di seguito un'implementazione con "un lock per oggetto": + +:: + + --- cache.c.refcnt-atomic 2003-12-11 15:50:54.000000000 +1100 + +++ cache.c.perobjectlock 2003-12-11 17:15:03.000000000 +1100 + @@ -6,11 +6,17 @@ + + struct object + { + + /* These two protected by cache_lock. */ + struct list_head list; + + int popularity; + + + atomic_t refcnt; + + + + /* Doesn't change once created. */ + int id; + + + + spinlock_t lock; /* Protects the name */ + char name[32]; + - int popularity; + }; + + static DEFINE_SPINLOCK(cache_lock); + @@ -77,6 +84,7 @@ + obj->id = id; + obj->popularity = 0; + atomic_set(&obj->refcnt, 1); /* The cache holds a reference */ + + spin_lock_init(&obj->lock); + + spin_lock_irqsave(&cache_lock, flags); + __cache_add(obj); + +Da notare che ho deciso che il contatore di popolarità dovesse essere +protetto da ``cache_lock`` piuttosto che dal *lock* dell'oggetto; questo +perché è logicamente parte dell'infrastruttura (come +:c:type:`struct list_head ` nell'oggetto). In questo modo, +in __cache_add(), non ho bisogno di trattenere il *lock* di ogni +oggetto mentre si cerca il meno popolare. + +Ho anche deciso che il campo id è immutabile, quindi non ho bisogno di +trattenere il lock dell'oggetto quando si usa __cache_find() +per leggere questo campo; il *lock* dell'oggetto è usato solo dal chiamante +che vuole leggere o scrivere il campo name. + +Inoltre, da notare che ho aggiunto un commento che descrive i dati che sono +protetti dal *lock*. Questo è estremamente importante in quanto descrive il +comportamento del codice, che altrimenti sarebbe di difficile comprensione +leggendo solamente il codice. E come dice Alan Cox: “Lock data, not code”. + +Problemi comuni +=============== + +Stallo: semplice ed avanzato +---------------------------- + +Esiste un tipo di baco dove un pezzo di codice tenta di trattenere uno +spinlock due volte: questo rimarrà in attesa attiva per sempre aspettando che +il *lock* venga rilasciato (in Linux spinlocks, rwlocks e mutex non sono +ricorsivi). +Questo è facile da diagnosticare: non è uno di quei problemi che ti tengono +sveglio 5 notti a parlare da solo. + +Un caso un pochino più complesso; immaginate d'avere una spazio condiviso +fra un softirq ed il contesto utente. Se usate spin_lock() per +proteggerlo, il contesto utente potrebbe essere interrotto da un softirq +mentre trattiene il lock, da qui il softirq rimarrà in attesa attiva provando +ad acquisire il *lock* già trattenuto nel contesto utente. + +Questi casi sono chiamati stalli (*deadlock*), e come mostrato qui sopra, +può succedere anche con un solo processore (Ma non sui sistemi +monoprocessore perché gli spinlock spariscano quando il kernel è compilato +con ``CONFIG_SMP``\ =n. Nonostante ciò, nel secondo caso avrete comunque +una corruzione dei dati). + +Questi casi sono facili da diagnosticare; sui sistemi multi-processore +il supervisione (*watchdog*) o l'opzione di compilazione ``DEBUG_SPINLOCK`` +(``include/linux/spinlock.h``) permettono di scovare immediatamente quando +succedono. + +Esiste un caso più complesso che è conosciuto come l'abbraccio della morte; +questo coinvolge due o più *lock*. Diciamo che avete un vettore di hash in cui +ogni elemento è uno spinlock a cui è associata una lista di elementi con lo +stesso hash. In un gestore di interruzioni software, dovete modificare un +oggetto e spostarlo su un altro hash; quindi dovrete trattenete lo spinlock +del vecchio hash e di quello nuovo, quindi rimuovere l'oggetto dal vecchio ed +inserirlo nel nuovo. + +Qui abbiamo due problemi. Primo, se il vostro codice prova a spostare un +oggetto all'interno della stessa lista, otterrete uno stallo visto che +tenterà di trattenere lo stesso *lock* due volte. Secondo, se la stessa +interruzione software su un altro processore sta tentando di spostare +un altro oggetto nella direzione opposta, potrebbe accadere quanto segue: + ++---------------------------------+---------------------------------+ +| CPU 1 | CPU 2 | ++=================================+=================================+ +| Trattiene *lock* A -> OK | Trattiene *lock* B -> OK | ++---------------------------------+---------------------------------+ +| Trattiene *lock* B -> attesa | Trattiene *lock* A -> attesa | ++---------------------------------+---------------------------------+ + +Table: Conseguenze + +Entrambe i processori rimarranno in attesa attiva sul *lock* per sempre, +aspettando che l'altro lo rilasci. Sembra e puzza come un blocco totale. + +Prevenire gli stalli +-------------------- + +I libri di testo vi diranno che se trattenete i *lock* sempre nello stesso +ordine non avrete mai un simile stallo. La pratica vi dirà che questo +approccio non funziona all'ingrandirsi del sistema: quando creo un nuovo +*lock* non ne capisco abbastanza del kernel per dire in quale dei 5000 *lock* +si incastrerà. + +I *lock* migliori sono quelli incapsulati: non vengono esposti nei file di +intestazione, e non vengono mai trattenuti fuori dallo stesso file. Potete +rileggere questo codice e vedere che non ci sarà mai uno stallo perché +non tenterà mai di trattenere un altro *lock* quando lo ha già. +Le persone che usano il vostro codice non devono nemmeno sapere che voi +state usando dei *lock*. + +Un classico problema deriva dall'uso di *callback* e di *hook*: se li +chiamate mentre trattenete un *lock*, rischiate uno stallo o un abbraccio +della morte (chi lo sa cosa farà una *callback*?). + +Ossessiva prevenzione degli stalli +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Gli stalli sono un problema, ma non così terribile come la corruzione dei dati. +Un pezzo di codice trattiene un *lock* di lettura, cerca in una lista, +fallisce nel trovare quello che vuole, quindi rilascia il *lock* di lettura, +trattiene un *lock* di scrittura ed inserisce un oggetto; questo genere di +codice presenta una corsa critica. + +corsa fra temporizzatori: un passatempo del kernel +-------------------------------------------------- + +I temporizzatori potrebbero avere dei problemi con le corse critiche. +Considerate una collezione di oggetti (liste, hash, eccetera) dove ogni oggetto +ha un temporizzatore che sta per distruggerlo. + +Se volete eliminare l'intera collezione (diciamo quando rimuovete un modulo), +potreste fare come segue:: + + /* THIS CODE BAD BAD BAD BAD: IF IT WAS ANY WORSE IT WOULD USE + HUNGARIAN NOTATION */ + spin_lock_bh(&list_lock); + + while (list) { + struct foo *next = list->next; + del_timer(&list->timer); + kfree(list); + list = next; + } + + spin_unlock_bh(&list_lock); + +Primo o poi, questo esploderà su un sistema multiprocessore perché un +temporizzatore potrebbe essere già partiro prima di spin_lock_bh(), +e prenderà il *lock* solo dopo spin_unlock_bh(), e cercherà +di eliminare il suo oggetto (che però è già stato eliminato). + +Questo può essere evitato controllando il valore di ritorno di +del_timer(): se ritorna 1, il temporizzatore è stato già +rimosso. Se 0, significa (in questo caso) che il temporizzatore è in +esecuzione, quindi possiamo fare come segue:: + + retry: + spin_lock_bh(&list_lock); + + while (list) { + struct foo *next = list->next; + if (!del_timer(&list->timer)) { + /* Give timer a chance to delete this */ + spin_unlock_bh(&list_lock); + goto retry; + } + kfree(list); + list = next; + } + + spin_unlock_bh(&list_lock); + +Un altro problema è l'eliminazione dei temporizzatori che si riavviano +da soli (chiamando add_timer() alla fine della loro esecuzione). +Dato che questo è un problema abbastanza comune con una propensione +alle corse critiche, dovreste usare del_timer_sync() +(``include/linux/timer.h``) per gestire questo caso. Questa ritorna il +numero di volte che il temporizzatore è stato interrotto prima che +fosse in grado di fermarlo senza che si riavviasse. + +Velocità della sincronizzazione +=============================== + +Ci sono tre cose importanti da tenere in considerazione quando si valuta +la velocità d'esecuzione di un pezzo di codice che necessita di +sincronizzazione. La prima è la concorrenza: quante cose rimangono in attesa +mentre qualcuno trattiene un *lock*. La seconda è il tempo necessario per +acquisire (senza contese) e rilasciare un *lock*. La terza è di usare meno +*lock* o di più furbi. Immagino che i *lock* vengano usati regolarmente, +altrimenti, non sareste interessati all'efficienza. + +La concorrenza dipende da quanto a lungo un *lock* è trattenuto: dovreste +trattenere un *lock* solo il tempo minimo necessario ma non un istante in più. +Nella memoria dell'esempio precedente, creiamo gli oggetti senza trattenere +il *lock*, poi acquisiamo il *lock* quando siamo pronti per inserirlo nella +lista. + +Il tempo di acquisizione di un *lock* dipende da quanto danno fa +l'operazione sulla *pipeline* (ovvero stalli della *pipeline*) e quant'è +probabile che il processore corrente sia stato anche l'ultimo ad acquisire +il *lock* (in pratica, il *lock* è nella memoria cache del processore +corrente?): su sistemi multi-processore questa probabilità precipita +rapidamente. Consideriamo un processore Intel Pentium III a 700Mhz: questo +esegue un'istruzione in 0.7ns, un incremento atomico richiede 58ns, acquisire +un *lock* che è nella memoria cache del processore richiede 160ns, e un +trasferimento dalla memoria cache di un altro processore richiede altri +170/360ns (Leggetevi l'articolo di Paul McKenney's `Linux Journal RCU +article `__). + +Questi due obiettivi sono in conflitto: trattenere un *lock* per il minor +tempo possibile potrebbe richiedere la divisione in più *lock* per diverse +parti (come nel nostro ultimo esempio con un *lock* per ogni oggetto), +ma questo aumenta il numero di acquisizioni di *lock*, ed il risultato +spesso è che tutto è più lento che con un singolo *lock*. Questo è un altro +argomento in favore della semplicità quando si parla di sincronizzazione. + +Il terzo punto è discusso di seguito: ci sono alcune tecniche per ridurre +il numero di sincronizzazioni che devono essere fatte. + +Read/Write Lock Variants +------------------------ + +Sia gli spinlock che i mutex hanno una variante per la lettura/scrittura +(read/write): ``rwlock_t`` e :c:type:`struct rw_semaphore `. +Queste dividono gli utenti in due categorie: i lettori e gli scrittori. +Se state solo leggendo i dati, potete acquisire il *lock* di lettura, ma +per scrivere avrete bisogno del *lock* di scrittura. Molti possono trattenere +il *lock* di lettura, ma solo uno scrittore alla volta può trattenere +quello di scrittura. + +Se il vostro codice si divide chiaramente in codice per lettori e codice +per scrittori (come nel nostro esempio), e il *lock* dei lettori viene +trattenuto per molto tempo, allora l'uso di questo tipo di *lock* può aiutare. +Questi sono leggermente più lenti rispetto alla loro versione normale, quindi +nella pratica l'uso di ``rwlock_t`` non ne vale la pena. + +Evitare i *lock*: Read Copy Update +-------------------------------------------- + +Esiste un metodo di sincronizzazione per letture e scritture detto +Read Copy Update. Con l'uso della tecnica RCU, i lettori possono scordarsi +completamente di trattenere i *lock*; dato che nel nostro esempio ci +aspettiamo d'avere più lettore che scrittori (altrimenti questa memoria +sarebbe uno spreco) possiamo dire che questo meccanismo permette +un'ottimizzazione. + +Come facciamo a sbarazzarci dei *lock* di lettura? Sbarazzarsi dei *lock* di +lettura significa che uno scrittore potrebbe cambiare la lista sotto al naso +dei lettori. Questo è abbastanza semplice: possiamo leggere una lista +concatenata se lo scrittore aggiunge elementi alla fine e con certe +precauzioni. Per esempio, aggiungendo ``new`` ad una lista concatenata +chiamata ``list``:: + + new->next = list->next; + wmb(); + list->next = new; + +La funzione wmb() è una barriera di sincronizzazione delle +scritture. Questa garantisce che la prima operazione (impostare l'elemento +``next`` del nuovo elemento) venga completata e vista da tutti i processori +prima che venga eseguita la seconda operazione (che sarebbe quella di mettere +il nuovo elemento nella lista). Questo è importante perché i moderni +compilatori ed i moderni processori possono, entrambe, riordinare le istruzioni +se non vengono istruiti altrimenti: vogliamo che i lettori non vedano +completamente il nuovo elemento; oppure che lo vedano correttamente e quindi +il puntatore ``next`` deve puntare al resto della lista. + +Fortunatamente, c'è una funzione che fa questa operazione sulle liste +:c:type:`struct list_head `: list_add_rcu() +(``include/linux/list.h``). + +Rimuovere un elemento dalla lista è anche più facile: sostituiamo il puntatore +al vecchio elemento con quello del suo successore, e i lettori vedranno +l'elemento o lo salteranno. + +:: + + list->next = old->next; + +La funzione list_del_rcu() (``include/linux/list.h``) fa esattamente +questo (la versione normale corrompe il vecchio oggetto, e non vogliamo che +accada). + +Anche i lettori devono stare attenti: alcuni processori potrebbero leggere +attraverso il puntatore ``next`` il contenuto dell'elemento successivo +troppo presto, ma non accorgersi che il contenuto caricato è sbagliato quando +il puntatore ``next`` viene modificato alla loro spalle. Ancora una volta +c'è una funzione che viene in vostro aiuto list_for_each_entry_rcu() +(``include/linux/list.h``). Ovviamente, gli scrittori possono usare +list_for_each_entry() dato che non ci possono essere due scrittori +in contemporanea. + +Il nostro ultimo dilemma è il seguente: quando possiamo realmente distruggere +l'elemento rimosso? Ricordate, un lettore potrebbe aver avuto accesso a questo +elemento proprio ora: se eliminiamo questo elemento ed il puntatore ``next`` +cambia, il lettore salterà direttamente nella spazzatura e scoppierà. Dobbiamo +aspettare finché tutti i lettori che stanno attraversando la lista abbiano +finito. Utilizziamo call_rcu() per registrare una funzione di +richiamo che distrugga l'oggetto quando tutti i lettori correnti hanno +terminato. In alternative, potrebbe essere usata la funzione +synchronize_rcu() che blocca l'esecuzione finché tutti i lettori +non terminano di ispezionare la lista. + +Ma come fa l'RCU a sapere quando i lettori sono finiti? Il meccanismo è +il seguente: innanzi tutto i lettori accedono alla lista solo fra la coppia +rcu_read_lock()/rcu_read_unlock() che disabilita la +prelazione così che i lettori non vengano sospesi mentre stanno leggendo +la lista. + +Poi, l'RCU aspetta finché tutti i processori non abbiano dormito almeno +una volta; a questo punto, dato che i lettori non possono dormire, possiamo +dedurre che un qualsiasi lettore che abbia consultato la lista durante la +rimozione abbia già terminato, quindi la *callback* viene eseguita. Il vero +codice RCU è un po' più ottimizzato di così, ma questa è l'idea di fondo. + +:: + + --- cache.c.perobjectlock 2003-12-11 17:15:03.000000000 +1100 + +++ cache.c.rcupdate 2003-12-11 17:55:14.000000000 +1100 + @@ -1,15 +1,18 @@ + #include + #include + #include + +#include + #include + #include + + struct object + { + - /* These two protected by cache_lock. */ + + /* This is protected by RCU */ + struct list_head list; + int popularity; + + + struct rcu_head rcu; + + + atomic_t refcnt; + + /* Doesn't change once created. */ + @@ -40,7 +43,7 @@ + { + struct object *i; + + - list_for_each_entry(i, &cache, list) { + + list_for_each_entry_rcu(i, &cache, list) { + if (i->id == id) { + i->popularity++; + return i; + @@ -49,19 +52,25 @@ + return NULL; + } + + +/* Final discard done once we know no readers are looking. */ + +static void cache_delete_rcu(void *arg) + +{ + + object_put(arg); + +} + + + /* Must be holding cache_lock */ + static void __cache_delete(struct object *obj) + { + BUG_ON(!obj); + - list_del(&obj->list); + - object_put(obj); + + list_del_rcu(&obj->list); + cache_num--; + + call_rcu(&obj->rcu, cache_delete_rcu); + } + + /* Must be holding cache_lock */ + static void __cache_add(struct object *obj) + { + - list_add(&obj->list, &cache); + + list_add_rcu(&obj->list, &cache); + if (++cache_num > MAX_CACHE_SIZE) { + struct object *i, *outcast = NULL; + list_for_each_entry(i, &cache, list) { + @@ -104,12 +114,11 @@ + struct object *cache_find(int id) + { + struct object *obj; + - unsigned long flags; + + - spin_lock_irqsave(&cache_lock, flags); + + rcu_read_lock(); + obj = __cache_find(id); + if (obj) + object_get(obj); + - spin_unlock_irqrestore(&cache_lock, flags); + + rcu_read_unlock(); + return obj; + } + +Da notare che i lettori modificano il campo popularity nella funzione +__cache_find(), e ora non trattiene alcun *lock*. Una soluzione +potrebbe essere quella di rendere la variabile ``atomic_t``, ma per l'uso +che ne abbiamo fatto qui, non ci interessano queste corse critiche perché un +risultato approssimativo è comunque accettabile, quindi non l'ho cambiato. + +Il risultato è che la funzione cache_find() non ha bisogno di alcuna +sincronizzazione con le altre funzioni, quindi è veloce su un sistema +multi-processore tanto quanto lo sarebbe su un sistema mono-processore. + +Esiste un'ulteriore ottimizzazione possibile: vi ricordate il codice originale +della nostra memoria dove non c'erano contatori di riferimenti e il chiamante +semplicemente tratteneva il *lock* prima di accedere ad un oggetto? Questo è +ancora possibile: se trattenete un *lock* nessuno potrà cancellare l'oggetto, +quindi non avete bisogno di incrementare e decrementare il contatore di +riferimenti. + +Ora, dato che il '*lock* di lettura' di un RCU non fa altro che disabilitare +la prelazione, un chiamante che ha sempre la prelazione disabilitata fra le +chiamate cache_find() e object_put() non necessita +di incrementare e decrementare il contatore di riferimenti. Potremmo +esporre la funzione __cache_find() dichiarandola non-static, +e quel chiamante potrebbe usare direttamente questa funzione. + +Il beneficio qui sta nel fatto che il contatore di riferimenti no +viene scritto: l'oggetto non viene alterato in alcun modo e quindi diventa +molto più veloce su sistemi molti-processore grazie alla loro memoria cache. + + +Dati per processore +------------------- + +Un'altra tecnica comunemente usata per evitare la sincronizzazione è quella +di duplicare le informazioni per ogni processore. Per esempio, se volete +avere un contatore di qualcosa, potreste utilizzare uno spinlock ed un +singolo contatore. Facile e pulito. + +Se questo dovesse essere troppo lento (solitamente non lo è, ma se avete +dimostrato che lo è devvero), potreste usare un contatore per ogni processore +e quindi non sarebbe più necessaria la mutua esclusione. Vedere +DEFINE_PER_CPU(), get_cpu_var() e put_cpu_var() +(``include/linux/percpu.h``). + +Il tipo di dato ``local_t``, la funzione cpu_local_inc() e tutte +le altre funzioni associate, sono di particolare utilità per semplici contatori +per-processore; su alcune architetture sono anche più efficienti +(``include/asm/local.h``). + +Da notare che non esiste un modo facile ed affidabile per ottenere il valore +di un simile contatore senza introdurre altri *lock*. In alcuni casi questo +non è un problema. + +Dati che sono usati prevalentemente dai gestori d'interruzioni +-------------------------------------------------------------- + +Se i dati vengono utilizzati sempre dallo stesso gestore d'interruzioni, +allora i *lock* non vi servono per niente: il kernel già vi garantisce che +il gestore d'interruzione non verrà eseguito in contemporanea su diversi +processori. + +Manfred Spraul fa notare che potreste comunque comportarvi così anche +se i dati vengono occasionalmente utilizzati da un contesto utente o +da un'interruzione software. Il gestore d'interruzione non utilizza alcun +*lock*, e tutti gli altri accessi verranno fatti così:: + + spin_lock(&lock); + disable_irq(irq); + ... + enable_irq(irq); + spin_unlock(&lock); + +La funzione disable_irq() impedisce al gestore d'interruzioni +d'essere eseguito (e aspetta che finisca nel caso fosse in esecuzione su +un altro processore). Lo spinlock, invece, previene accessi simultanei. +Naturalmente, questo è più lento della semplice chiamata +spin_lock_irq(), quindi ha senso solo se questo genere di accesso +è estremamente raro. + + +Quali funzioni possono essere chiamate in modo sicuro dalle interruzioni? +========================================================================= + +Molte funzioni del kernel dormono (in sostanza, chiamano schedule()) +direttamente od indirettamente: non potete chiamarle se trattenere uno +spinlock o avete la prelazione disabilitata, mai. Questo significa che +dovete necessariamente essere nel contesto utente: chiamarle da un +contesto d'interruzione è illegale. + +Alcune funzioni che dormono +--------------------------- + +Le più comuni sono elencate qui di seguito, ma solitamente dovete leggere +il codice per scoprire se altre chiamate sono sicure. Se chiunque altro +le chiami dorme, allora dovreste poter dormire anche voi. In particolar +modo, le funzioni di registrazione e deregistrazione solitamente si +aspettano d'essere chiamante da un contesto utente e quindi che possono +dormire. + +- Accessi allo spazio utente: + + - copy_from_user() + + - copy_to_user() + + - get_user() + + - put_user() + +- kmalloc(GFP_KERNEL) ` + +- mutex_lock_interruptible() and + mutex_lock() + + C'è anche mutex_trylock() che però non dorme. + Comunque, non deve essere usata in un contesto d'interruzione dato + che la sua implementazione non è sicura in quel contesto. + Anche mutex_unlock() non dorme mai. Non può comunque essere + usata in un contesto d'interruzione perché un mutex deve essere rilasciato + dallo stesso processo che l'ha acquisito. + +Alcune funzioni che non dormono +------------------------------- + +Alcune funzioni possono essere chiamate tranquillamente da qualsiasi +contesto, o trattenendo un qualsiasi *lock*. + +- printk() + +- kfree() + +- add_timer() e del_timer() + +Riferimento per l'API dei Mutex +=============================== + +.. kernel-doc:: include/linux/mutex.h + :internal: + +.. kernel-doc:: kernel/locking/mutex.c + :export: + +Riferimento per l'API dei Futex +=============================== + +.. kernel-doc:: kernel/futex/core.c + :internal: + +.. kernel-doc:: kernel/futex/futex.h + :internal: + +.. kernel-doc:: kernel/futex/pi.c + :internal: + +.. kernel-doc:: kernel/futex/requeue.c + :internal: + +.. kernel-doc:: kernel/futex/waitwake.c + :internal: + +Approfondimenti +=============== + +- ``Documentation/locking/spinlocks.rst``: la guida di Linus Torvalds agli + spinlock del kernel. + +- Unix Systems for Modern Architectures: Symmetric Multiprocessing and + Caching for Kernel Programmers. + + L'introduzione alla sincronizzazione a livello di kernel di Curt Schimmel + è davvero ottima (non è scritta per Linux, ma approssimativamente si adatta + a tutte le situazioni). Il libro è costoso, ma vale ogni singolo spicciolo + per capire la sincronizzazione nei sistemi multi-processore. + [ISBN: 0201633388] + +Ringraziamenti +============== + +Grazie a Telsa Gwynne per aver formattato questa guida in DocBook, averla +pulita e aggiunto un po' di stile. + +Grazie a Martin Pool, Philipp Rumpf, Stephen Rothwell, Paul Mackerras, +Ruedi Aschwanden, Alan Cox, Manfred Spraul, Tim Waugh, Pete Zaitcev, +James Morris, Robert Love, Paul McKenney, John Ashby per aver revisionato, +corretto, maledetto e commentato. + +Grazie alla congrega per non aver avuto alcuna influenza su questo documento. + +Glossario +========= + +prelazione + Prima del kernel 2.5, o quando ``CONFIG_PREEMPT`` non è impostato, i processi + in contesto utente non si avvicendano nell'esecuzione (in pratica, il + processo userà il processore fino al proprio termine, a meno che non ci siano + delle interruzioni). Con l'aggiunta di ``CONFIG_PREEMPT`` nella versione + 2.5.4 questo è cambiato: quando si è in contesto utente, processi con una + priorità maggiore possono subentrare nell'esecuzione: gli spinlock furono + cambiati per disabilitare la prelazioni, anche su sistemi monoprocessore. + +bh + Bottom Half: per ragioni storiche, le funzioni che contengono '_bh' nel + loro nome ora si riferiscono a qualsiasi interruzione software; per esempio, + spin_lock_bh() blocca qualsiasi interuzione software sul processore + corrente. I *Bottom Halves* sono deprecati, e probabilmente verranno + sostituiti dai tasklet. In un dato momento potrà esserci solo un + *bottom half* in esecuzione. + +contesto d'interruzione + Non è il contesto utente: qui si processano le interruzioni hardware e + software. La macro in_interrupt() ritorna vero. + +contesto utente + Il kernel che esegue qualcosa per conto di un particolare processo (per + esempio una chiamata di sistema) o di un thread del kernel. Potete + identificare il processo con la macro ``current``. Da non confondere + con lo spazio utente. Può essere interrotto sia da interruzioni software + che hardware. + +interruzione hardware + Richiesta di interruzione hardware. in_hardirq() ritorna vero in un + gestore d'interruzioni hardware. + +interruzione software / softirq + Gestore di interruzioni software: in_hardirq() ritorna falso; + in_softirq() ritorna vero. I tasklet e le softirq sono entrambi + considerati 'interruzioni software'. + + In soldoni, un softirq è uno delle 32 interruzioni software che possono + essere eseguite su più processori in contemporanea. A volte si usa per + riferirsi anche ai tasklet (in pratica tutte le interruzioni software). + +monoprocessore / UP + (Uni-Processor) un solo processore, ovvero non è SMP. (``CONFIG_SMP=n``). + +multi-processore / SMP + (Symmetric Multi-Processor) kernel compilati per sistemi multi-processore + (``CONFIG_SMP=y``). + +spazio utente + Un processo che esegue il proprio codice fuori dal kernel. + +tasklet + Un'interruzione software registrabile dinamicamente che ha la garanzia + d'essere eseguita solo su un processore alla volta. + +timer + Un'interruzione software registrabile dinamicamente che viene eseguita + (circa) in un determinato momento. Quando è in esecuzione è come un tasklet + (infatti, sono chiamati da ``TIMER_SOFTIRQ``). diff --git a/Documentation/translations/it_IT/maintainer/configure-git.rst b/Documentation/translations/it_IT/maintainer/configure-git.rst new file mode 100644 index 000000000..8316fa539 --- /dev/null +++ b/Documentation/translations/it_IT/maintainer/configure-git.rst @@ -0,0 +1,10 @@ +.. include:: ../disclaimer-ita.rst + +:Original: Documentation/process/botching-up-ioctls.rst + +.. _it_configuregit: + +Configurare Git +=============== + +.. note:: To be translated diff --git a/Documentation/translations/it_IT/networking/netdev-FAQ.rst b/Documentation/translations/it_IT/networking/netdev-FAQ.rst new file mode 100644 index 000000000..8a1e04958 --- /dev/null +++ b/Documentation/translations/it_IT/networking/netdev-FAQ.rst @@ -0,0 +1,13 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/maintainer-netdev.rst ` + +.. _it_netdev-FAQ: + +========== +netdev FAQ +========== + +.. warning:: + + TODO ancora da tradurre diff --git a/Documentation/translations/it_IT/process/1.Intro.rst b/Documentation/translations/it_IT/process/1.Intro.rst new file mode 100644 index 000000000..c1be6dc39 --- /dev/null +++ b/Documentation/translations/it_IT/process/1.Intro.rst @@ -0,0 +1,297 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/1.Intro.rst ` +:Translator: Alessia Mantegazza + +.. _it_development_intro: + +Introduzione +============ + +Riepilogo generale +------------------ + +Il resto di questa sezione riguarda il processo di sviluppo del kernel e +quella sorta di frustrazione che gli sviluppatori e i loro datori di lavoro +potrebbero dover affrontare. Ci sono molte ragioni per le quali del codice +per il kernel debba essere incorporato nel kernel ufficiale, fra le quali: +disponibilità immediata agli utilizzatori, supporto della comunità in +differenti modalità, e la capacità di influenzare la direzione dello sviluppo +del kernel. +Il codice che contribuisce al kernel Linux deve essere reso disponibile sotto +una licenza GPL-compatibile. + +La sezione :ref:`it_development_process` introduce il processo di sviluppo, +il ciclo di rilascio del kernel, ed i meccanismi della finestra +d'incorporazione. Il capitolo copre le varie fasi di una modifica: sviluppo, +revisione e ciclo d'incorporazione. Ci sono alcuni dibattiti su strumenti e +liste di discussione. Gli sviluppatori che sono in attesa di poter sviluppare +qualcosa per il kernel sono invitati ad individuare e sistemare bachi come +esercizio iniziale. + +La sezione :ref:`it_development_early_stage` copre i primi stadi della +pianificazione di un progetto di sviluppo, con particolare enfasi sul +coinvolgimento della comunità, il prima possibile. + +La sezione :ref:`it_development_coding` riguarda il processo di scrittura +del codice. Qui, sono esposte le diverse insidie che sono state già affrontate +da altri sviluppatori. Il capitolo copre anche alcuni dei requisiti per le +modifiche, ed esiste un'introduzione ad alcuni strumenti che possono aiutarvi +nell'assicurarvi che le modifiche per il kernel siano corrette. + +La sezione :ref:`it_development_posting` parla del processo di pubblicazione +delle modifiche per la revisione. Per essere prese in considerazione dalla +comunità di sviluppo, le modifiche devono essere propriamente formattate ed +esposte, e devono essere inviate nel posto giusto. Seguire i consigli presenti +in questa sezione dovrebbe essere d'aiuto nell'assicurare la migliore +accoglienza possibile del vostro lavoro. + +La sezione :ref:`it_development_followthrough` copre ciò che accade dopo +la pubblicazione delle modifiche; a questo punto il lavoro è lontano +dall'essere concluso. Lavorare con i revisori è una parte cruciale del +processo di sviluppo; questa sezione offre una serie di consigli su come +evitare problemi in questa importante fase. Gli sviluppatori sono diffidenti +nell'affermare che il lavoro è concluso quando una modifica è incorporata nei +sorgenti principali. + +La sezione :ref:`it_development_advancedtopics` introduce un paio di argomenti +"avanzati": gestire le modifiche con git e controllare le modifiche pubblicate +da altri. + +La sezione :ref:`it_development_conclusion` chiude il documento con dei +riferimenti ad altre fonti che forniscono ulteriori informazioni sullo sviluppo +del kernel. + +Di cosa parla questo documento +------------------------------ + +Il kernel Linux, ha oltre 8 milioni di linee di codice e ben oltre 1000 +contributori ad ogni rilascio; è uno dei più vasti e più attivi software +liberi progettati mai esistiti. Sin dal sul modesto inizio nel 1991, +questo kernel si è evoluto nel miglior componente per sistemi operativi +che fanno funzionare piccoli riproduttori musicali, PC, grandi super computer +e tutte le altre tipologie di sistemi fra questi estremi. È una soluzione +robusta, efficiente ed adattabile a praticamente qualsiasi situazione. + +Con la crescita di Linux è arrivato anche un aumento di sviluppatori +(ed aziende) desiderosi di partecipare a questo sviluppo. I produttori di +hardware vogliono assicurarsi che il loro prodotti siano supportati da Linux, +rendendo questi prodotti attrattivi agli utenti Linux. I produttori di +sistemi integrati, che usano Linux come componente di un prodotto integrato, +vogliono che Linux sia capace ed adeguato agli obiettivi ed il più possibile +alla mano. Fornitori ed altri produttori di software che basano i propri +prodotti su Linux hanno un chiaro interesse verso capacità, prestazioni ed +affidabilità del kernel Linux. E gli utenti finali, anche, spesso vorrebbero +cambiare Linux per renderlo più aderente alle proprie necessità. + +Una delle caratteristiche più coinvolgenti di Linux è quella dell'accessibilità +per gli sviluppatori; chiunque con le capacità richieste può migliorare +Linux ed influenzarne la direzione di sviluppo. Prodotti non open-source non +possono offrire questo tipo di apertura, che è una caratteristica del software +libero. Ma, anzi, il kernel è persino più aperto rispetto a molti altri +progetti di software libero. Un classico ciclo di sviluppo trimestrale può +coinvolgere 1000 sviluppatori che lavorano per più di 100 differenti aziende +(o per nessuna azienda). + +Lavorare con la comunità di sviluppo del kernel non è particolarmente +difficile. Ma, ciononostante, diversi potenziali contributori hanno trovato +delle difficoltà quando hanno cercato di lavorare sul kernel. La comunità del +kernel utilizza un proprio modo di operare che gli permette di funzionare +agevolmente (e genera un prodotto di alta qualità) in un ambiente dove migliaia +di stringhe di codice sono modificate ogni giorni. Quindi non deve sorprendere +che il processo di sviluppo del kernel differisca notevolmente dai metodi di +sviluppo privati. + +Il processo di sviluppo del Kernel può, dall'altro lato, risultare +intimidatorio e strano ai nuovi sviluppatori, ma ha dietro di se buone ragioni +e solide esperienze. Uno sviluppatore che non comprende i modi della comunità +del kernel (o, peggio, che cerchi di aggirarli o violarli) avrà un'esperienza +deludente nel proprio bagaglio. La comunità di sviluppo, sebbene sia utile +a coloro che cercano di imparare, ha poco tempo da dedicare a coloro che non +ascoltano o coloro che non sono interessati al processo di sviluppo. + +Si spera che coloro che leggono questo documento saranno in grado di evitare +queste esperienze spiacevoli. C'è molto materiale qui, ma lo sforzo della +lettura sarà ripagato in breve tempo. La comunità di sviluppo ha sempre +bisogno di sviluppatori che vogliano aiutare a rendere il kernel migliore; +il testo seguente potrebbe esservi d'aiuto - o essere d'aiuto ai vostri +collaboratori- per entrare a far parte della nostra comunità. + +Crediti +------- + +Questo documento è stato scritto da Jonathan Corbet, corbet@lwn.net. +È stato migliorato da Johannes Berg, James Berry, Alex Chiang, Roland +Dreier, Randy Dunlap, Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh, +Amanda McPherson, Andrew Morton, Andrew Price, Tsugikazu Shibata e Jochen Voß. + +Questo lavoro è stato supportato dalla Linux Foundation; un ringraziamento +speciale ad Amanda McPherson, che ha visto il valore di questo lavoro e lo ha +reso possibile. + +L'importanza d'avere il codice nei sorgenti principali +------------------------------------------------------ + +Alcune aziende e sviluppatori ogni tanto si domandano perché dovrebbero +preoccuparsi di apprendere come lavorare con la comunità del kernel e di +inserire il loro codice nel ramo di sviluppo principale (per ramo principale +s'intende quello mantenuto da Linus Torvalds e usato come base dai +distributori Linux). Nel breve termine, contribuire al codice può sembrare +un costo inutile; può sembra più facile tenere separato il proprio codice e +supportare direttamente i suoi utilizzatori. La verità è che il tenere il +codice separato ("fuori dai sorgenti", *"out-of-tree"*) è un falso risparmio. + +Per dimostrare i costi di un codice "fuori dai sorgenti", eccovi +alcuni aspetti rilevanti del processo di sviluppo kernel; la maggior parte +di essi saranno approfonditi dettagliatamente più avanti in questo documento. +Considerate: + +- Il codice che è stato inserito nel ramo principale del kernel è disponibile + a tutti gli utilizzatori Linux. Sarà automaticamente presente in tutte le + distribuzioni che lo consentono. Non c'è bisogno di: driver per dischi, + scaricare file, o della scocciatura del dover supportare diverse versioni di + diverse distribuzioni; funziona già tutto, per gli sviluppatori e per gli + utilizzatori. L'inserimento nel ramo principale risolve un gran numero di + problemi di distribuzione e di supporto. + +- Nonostante gli sviluppatori kernel si sforzino di tenere stabile + l'interfaccia dello spazio utente, quella interna al kernel è in continuo + cambiamento. La mancanza di un'interfaccia interna è deliberatamente una + decisione di progettazione; ciò permette che i miglioramenti fondamentali + vengano fatti in un qualsiasi momento e che risultino fatti con un codice di + alta qualità. Ma una delle conseguenze di questa politica è che qualsiasi + codice "fuori dai sorgenti" richiede costante manutenzione per renderlo + funzionante coi kernel più recenti. Tenere un codice "fuori dai sorgenti" + richiede una mole di lavoro significativa solo per farlo funzionare. + + Invece, il codice che si trova nel ramo principale non necessita di questo + tipo di lavoro poiché ad ogni sviluppatore che faccia una modifica alle + interfacce viene richiesto di sistemare anche il codice che utilizza + quell'interfaccia. Quindi, il codice che è stato inserito nel ramo principale + ha dei costi di mantenimento significativamente più bassi. + +- Oltre a ciò, spesso il codice che è all'interno del kernel sarà migliorato da + altri sviluppatori. Dare pieni poteri alla vostra comunità di utenti e ai + clienti può portare a sorprendenti risultati che migliorano i vostri + prodotti. + +- Il codice kernel è soggetto a revisioni, sia prima che dopo l'inserimento + nel ramo principale. Non importa quanto forti fossero le abilità dello + sviluppatore originale, il processo di revisione troverà il modo di migliore + il codice. Spesso la revisione trova bachi importanti e problemi di + sicurezza. Questo è particolarmente vero per il codice che è stato + sviluppato in un ambiente chiuso; tale codice ottiene un forte beneficio + dalle revisioni provenienti da sviluppatori esteri. Il codice + "fuori dai sorgenti", invece, è un codice di bassa qualità. + +- La partecipazione al processo di sviluppo costituisce la vostra via per + influenzare la direzione di sviluppo del kernel. Gli utilizzatori che + "reclamano da bordo campo" sono ascoltati, ma gli sviluppatori attivi + hanno una voce più forte - e la capacità di implementare modifiche che + renderanno il kernel più funzionale alle loro necessità. + +- Quando il codice è gestito separatamente, esiste sempre la possibilità che + terze parti contribuiscano con una differente implementazione che fornisce + le stesse funzionalità. Se dovesse accadere, l'inserimento del codice + diventerà molto più difficile - fino all'impossibilità. Poi, dovrete far + fronte a delle alternative poco piacevoli, come: (1) mantenere un elemento + non standard "fuori dai sorgenti" per un tempo indefinito, o (2) abbandonare + il codice e far migrare i vostri utenti alla versione "nei sorgenti". + +- Contribuire al codice è l'azione fondamentale che fa funzionare tutto il + processo. Contribuendo attraverso il vostro codice potete aggiungere nuove + funzioni al kernel e fornire competenze ed esempi che saranno utili ad + altri sviluppatori. Se avete sviluppato del codice Linux (o state pensando + di farlo), avete chiaramente interesse nel far proseguire il successo di + questa piattaforma. Contribuire al codice è une delle migliori vie per + aiutarne il successo. + +Il ragionamento sopra citato si applica ad ogni codice "fuori dai sorgenti" +dal kernel, incluso il codice proprietario distribuito solamente in formato +binario. Ci sono, comunque, dei fattori aggiuntivi che dovrebbero essere +tenuti in conto prima di prendere in considerazione qualsiasi tipo di +distribuzione binaria di codice kernel. Questo include che: + +- Le questioni legali legate alla distribuzione di moduli kernel proprietari + sono molto nebbiose; parecchi detentori di copyright sul kernel credono che + molti moduli binari siano prodotti derivati del kernel e che, come risultato, + la loro diffusione sia una violazione della licenza generale di GNU (della + quale si parlerà più avanti). L'autore qui non è un avvocato, e + niente in questo documento può essere considerato come un consiglio legale. + Il vero stato legale dei moduli proprietari può essere determinato + esclusivamente da un giudice. Ma l'incertezza che perseguita quei moduli + è lì comunque. + +- I moduli binari aumentano di molto la difficoltà di fare debugging del + kernel, al punto che la maggior parte degli sviluppatori del kernel non + vorranno nemmeno tentare. Quindi la diffusione di moduli esclusivamente + binari renderà difficile ai vostri utilizzatori trovare un supporto dalla + comunità. + +- Il supporto è anche difficile per i distributori di moduli binari che devono + fornire una versione del modulo per ogni distribuzione e per ogni versione + del kernel che vogliono supportate. Per fornire una copertura ragionevole e + comprensiva, può essere richiesto di produrre dozzine di singoli moduli. + E inoltre i vostri utilizzatori dovranno aggiornare il vostro modulo + separatamente ogni volta che aggiornano il loro kernel. + +- Tutto ciò che è stato detto prima riguardo alla revisione del codice si + applica doppiamente al codice proprietario. Dato che questo codice non è + del tutto disponibile, non può essere revisionato dalla comunità e avrà, + senza dubbio, seri problemi. + +I produttori di sistemi integrati, in particolare, potrebbero esser tentati +dall'evitare molto di ciò che è stato detto in questa sezione, credendo che +stiano distribuendo un prodotto finito che utilizza una versione del kernel +immutabile e che non richiede un ulteriore sviluppo dopo il rilascio. Questa +idea non comprende il valore di una vasta revisione del codice e il valore +del permettere ai propri utenti di aggiungere funzionalità al vostro prodotto. +Ma anche questi prodotti, hanno una vita commerciale limitata, dopo la quale +deve essere rilasciata una nuova versione. A quel punto, i produttori il cui +codice è nel ramo principale di sviluppo avranno un codice ben mantenuto e +saranno in una posizione migliore per ottenere velocemente un nuovo prodotto +pronto per essere distribuito. + + +Licenza +------- + +IL codice Linux utilizza diverse licenze, ma il codice completo deve essere +compatibile con la seconda versione della licenza GNU General Public License +(GPLv2), che è la licenza che copre la distribuzione del kernel. +Nella pratica, ciò significa che tutti i contributi al codice sono coperti +anche'essi dalla GPLv2 (con, opzionalmente, una dicitura che permette la +possibilità di distribuirlo con licenze più recenti di GPL) o dalla licenza +three-clause BSD. Qualsiasi contributo che non è coperto da una licenza +compatibile non verrà accettata nel kernel. + +Per il codice sottomesso al kernel non è necessario (o richiesto) la +concessione del Copyright. Tutto il codice inserito nel ramo principale del +kernel conserva la sua proprietà originale; ne risulta che ora il kernel abbia +migliaia di proprietari. + +Una conseguenza di questa organizzazione della proprietà è che qualsiasi +tentativo di modifica della licenza del kernel è destinata ad un quasi sicuro +fallimento. Esistono alcuni scenari pratici nei quali il consenso di tutti +i detentori di copyright può essere ottenuto (o il loro codice verrà rimosso +dal kernel). Quindi, in sostanza, non esiste la possibilità che si giunga ad +una versione 3 della licenza GPL nel prossimo futuro. + +È imperativo che tutto il codice che contribuisce al kernel sia legittimamente +software libero. Per questa ragione, un codice proveniente da un contributore +anonimo (o sotto pseudonimo) non verrà accettato. È richiesto a tutti i +contributori di firmare il proprio codice, attestando così che quest'ultimo +può essere distribuito insieme al kernel sotto la licenza GPL. Il codice che +non è stato licenziato come software libero dal proprio creatore, o che +potrebbe creare problemi di copyright per il kernel (come il codice derivante +da processi di ingegneria inversa senza le opportune tutele), non può essere +diffuso. + +Domande relative a questioni legate al copyright sono frequenti nelle liste +di discussione dedicate allo sviluppo di Linux. Tali quesiti, normalmente, +non riceveranno alcuna risposta, ma una cosa deve essere tenuta presente: +le persone che risponderanno a quelle domande non sono avvocati e non possono +fornire supporti legali. Se avete questioni legali relative ai sorgenti +del codice Linux, non esiste alternativa che quella di parlare con un +avvocato esperto nel settore. Fare affidamento sulle risposte ottenute da +una lista di discussione tecnica è rischioso. diff --git a/Documentation/translations/it_IT/process/2.Process.rst b/Documentation/translations/it_IT/process/2.Process.rst new file mode 100644 index 000000000..62826034e --- /dev/null +++ b/Documentation/translations/it_IT/process/2.Process.rst @@ -0,0 +1,534 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/2.Process.rst ` +:Translator: Alessia Mantegazza + +.. _it_development_process: + +Come funziona il processo di sviluppo +===================================== + +Lo sviluppo del Kernel agli inizi degli anno '90 era abbastanza libero, con +un numero di utenti e sviluppatori relativamente basso. Con una base +di milioni di utenti e con 2000 sviluppatori coinvolti nel giro di un anno, +il kernel da allora ha messo in atto un certo numero di procedure per rendere +lo sviluppo più agevole. È richiesta una solida conoscenza di come tale +processo si svolge per poter esserne parte attiva. + +Il quadro d'insieme +------------------- + +Gli sviluppatori kernel utilizzano un calendario di rilascio generico, dove +ogni due o tre mesi viene effettuata un rilascio importante del kernel. +I rilasci più recenti sono stati: + + ====== ================= + 5.0 3 marzo, 2019 + 5.1 5 maggio, 2019 + 5.2 7 luglio, 2019 + 5.3 15 settembre, 2019 + 5.4 24 novembre, 2019 + 5.5 6 gennaio, 2020 + ====== ================= + +Ciascun rilascio 5.x è un importante rilascio del kernel con nuove +funzionalità, modifiche interne dell'API, e molto altro. Un tipico +rilascio contiene quasi 13,000 gruppi di modifiche con ulteriori +modifiche a parecchie migliaia di linee di codice. La 5.x. è pertanto la +linea di confine nello sviluppo del kernel Linux; il kernel utilizza un sistema +di sviluppo continuo che integra costantemente nuove importanti modifiche. + +Viene seguita una disciplina abbastanza lineare per l'inclusione delle +patch di ogni rilascio. All'inizio di ogni ciclo di sviluppo, la +"finestra di inclusione" viene dichiarata aperta. In quel momento il codice +ritenuto sufficientemente stabile(e che è accettato dalla comunità di sviluppo) +viene incluso nel ramo principale del kernel. La maggior parte delle +patch per un nuovo ciclo di sviluppo (e tutte le più importanti modifiche) +saranno inserite durante questo periodo, ad un ritmo che si attesta sulle +1000 modifiche ("patch" o "gruppo di modifiche") al giorno. + +(per inciso, vale la pena notare che i cambiamenti integrati durante la +"finestra di inclusione" non escono dal nulla; questi infatti, sono stati +raccolti e, verificati in anticipo. Il funzionamento di tale procedimento +verrà descritto dettagliatamente più avanti). + +La finestra di inclusione resta attiva approssimativamente per due settimane. +Al termine di questo periodo, Linus Torvald dichiarerà che la finestra è +chiusa e rilascerà il primo degli "rc" del kernel. +Per il kernel che è destinato ad essere 5.6, per esempio, il rilascio +che emerge al termine della finestra d'inclusione si chiamerà 5.6-rc1. +Questo rilascio indica che il momento di aggiungere nuovi componenti è +passato, e che è iniziato il periodo di stabilizzazione del prossimo kernel. + +Nelle successive sei/dieci settimane, potranno essere sottoposte solo modifiche +che vanno a risolvere delle problematiche. Occasionalmente potrà essere +consentita una modifica più consistente, ma tali occasioni sono rare. +Gli sviluppatori che tenteranno di aggiungere nuovi elementi al di fuori della +finestra di inclusione, tendenzialmente, riceveranno un accoglienza poco +amichevole. Come regola generale: se vi perdete la finestra di inclusione per +un dato componente, la cosa migliore da fare è aspettare il ciclo di sviluppo +successivo (un'eccezione può essere fatta per i driver per hardware non +supportati in precedenza; se toccano codice non facente parte di quello +attuale, che non causino regressioni e che potrebbero essere aggiunti in +sicurezza in un qualsiasi momento) + +Mentre le correzioni si aprono la loro strada all'interno del ramo principale, +il ritmo delle modifiche rallenta col tempo. Linus rilascia un nuovo +kernel -rc circa una volta alla settimana; e ne usciranno circa 6 o 9 prima +che il kernel venga considerato sufficientemente stabile e che il rilascio +finale venga fatto. A quel punto tutto il processo ricomincerà. + +Esempio: ecco com'è andato il ciclo di sviluppo della versione 5.4 +(tutte le date si collocano nel 2018) + + + ============== ======================================= + 15 settembre 5.3 rilascio stabile + 30 settembre 5.4-rc1, finestra di inclusione chiusa + 6 ottobre 5.4-rc2 + 13 ottobre 5.4-rc3 + 20 ottobre 5.4-rc4 + 27 ottobre 5.4-rc5 + 3 novembre 5.4-rc6 + 10 novembre 5.4-rc7 + 17 novembre 5.4-rc8 + 24 novembre 5.4 rilascio stabile + ============== ======================================= + +In che modo gli sviluppatori decidono quando chiudere il ciclo di sviluppo e +creare quindi una rilascio stabile? Un metro valido è il numero di regressioni +rilevate nel precedente rilascio. Nessun baco è il benvenuto, ma quelli che +procurano problemi su sistemi che hanno funzionato in passato sono considerati +particolarmente seri. Per questa ragione, le modifiche che portano ad una +regressione sono viste sfavorevolmente e verranno quasi sicuramente annullate +durante il periodo di stabilizzazione. + +L'obiettivo degli sviluppatori è quello di aggiustare tutte le regressioni +conosciute prima che avvenga il rilascio stabile. Nel mondo reale, questo +tipo di perfezione difficilmente viene raggiunta; esistono troppe variabili +in un progetto di questa portata. Arriva un punto dove ritardare il rilascio +finale peggiora la situazione; la quantità di modifiche in attesa della +prossima finestra di inclusione crescerà enormemente, creando ancor più +regressioni al giro successivo. Quindi molti kernel 5.x escono con una +manciata di regressioni delle quali, si spera, nessuna è grave. + +Una volta che un rilascio stabile è fatto, il suo costante mantenimento è +affidato al "squadra stabilità", attualmente composta da Greg Kroah-Hartman. +Questa squadra rilascia occasionalmente degli aggiornamenti relativi al +rilascio stabile usando la numerazione 5.x.y. Per essere presa in +considerazione per un rilascio d'aggiornamento, una modifica deve: +(1) correggere un baco importante (2) essere già inserita nel ramo principale +per il prossimo sviluppo del kernel. Solitamente, passato il loro rilascio +iniziale, i kernel ricevono aggiornamenti per più di un ciclo di sviluppo. +Quindi, per esempio, la storia del kernel 5.2 appare così (anno 2019): + + ============== =============================== + 7 luglio 5.2 rilascio stabile + 14 luglio 5.2.1 + 21 luglio 5.2.2 + 26 luglio 5.2.3 + 28 luglio 5.2.4 + 31 luglio 5.2.5 + ... ... + 11 ottobre 5.2.21 + ============== =============================== + +La 5.2.21 fu l'aggiornamento finale per la versione 5.2. + +Alcuni kernel sono destinati ad essere kernel a "lungo termine"; questi +riceveranno assistenza per un lungo periodo di tempo. Al momento in cui +scriviamo, i manutentori dei kernel stabili a lungo termine sono: + + ====== ================================ ========================================== + 3.16 Ben Hutchings (kernel stabile molto più a lungo termine) + 4.4 Greg Kroah-Hartman e Sasha Levin (kernel stabile molto più a lungo termine) + 4.9 Greg Kroah-Hartman e Sasha Levin + 4.14 Greg Kroah-Hartman e Sasha Levin + 4.19 Greg Kroah-Hartman e Sasha Levin + 5.4i Greg Kroah-Hartman e Sasha Levin + ====== ================================ ========================================== + + +Questa selezione di kernel di lungo periodo sono puramente dovuti ai loro +manutentori, alla loro necessità e al tempo per tenere aggiornate proprio +quelle versioni. Non ci sono altri kernel a lungo termine in programma per +alcun rilascio in arrivo. + +Il ciclo di vita di una patch +----------------------------- + +Le patch non passano direttamente dalla tastiera dello sviluppatori +al ramo principale del kernel. Esiste, invece, una procedura disegnata +per assicurare che ogni patch sia di buona qualità e desiderata nel +ramo principale. Questo processo avviene velocemente per le correzioni +meno importanti, o, nel caso di patch ampie e controverse, va avanti per anni. +Per uno sviluppatore la maggior frustrazione viene dalla mancanza di +comprensione di questo processo o dai tentativi di aggirarlo. + +Nella speranza di ridurre questa frustrazione, questo documento spiegherà +come una patch viene inserita nel kernel. Ciò che segue è un'introduzione +che descrive il processo ideale. Approfondimenti verranno invece trattati +più avanti. + +Una patch attraversa, generalmente, le seguenti fasi: + + - Progetto. In questa fase sono stabilite quelli che sono i requisiti + della modifica - e come verranno soddisfatti. Il lavoro di progettazione + viene spesso svolto senza coinvolgere la comunità, ma è meglio renderlo + il più aperto possibile; questo può far risparmiare molto tempo evitando + eventuali riprogettazioni successive. + + - Prima revisione. Le patch vengono pubblicate sulle liste di discussione + interessate, e gli sviluppatori in quella lista risponderanno coi loro + commenti. Se si svolge correttamente, questo procedimento potrebbe far + emergere problemi rilevanti in una patch. + + - Revisione più ampia. Quando la patch è quasi pronta per essere inserita + nel ramo principale, un manutentore importante del sottosistema dovrebbe + accettarla - anche se, questa accettazione non è una garanzia che la + patch arriverà nel ramo principale. La patch sarà visibile nei sorgenti + del sottosistema in questione e nei sorgenti -next (descritti sotto). + Quando il processo va a buon fine, questo passo porta ad una revisione + più estesa della patch e alla scoperta di problemi d'integrazione + con il lavoro altrui. + +- Per favore, tenete da conto che la maggior parte dei manutentori ha + anche un lavoro quotidiano, quindi integrare le vostre patch potrebbe + non essere la loro priorità più alta. Se una vostra patch riceve + dei suggerimenti su dei cambiamenti necessari, dovreste applicare + quei cambiamenti o giustificare perché non sono necessari. Se la vostra + patch non riceve alcuna critica ma non è stata integrata dal + manutentore del driver o sottosistema, allora dovreste continuare con + i necessari aggiornamenti per mantenere la patch aggiornata al kernel + più recente cosicché questa possa integrarsi senza problemi; continuate + ad inviare gli aggiornamenti per essere revisionati e integrati. + + - Inclusione nel ramo principale. Eventualmente, una buona patch verrà + inserita all'interno nel repositorio principale, gestito da + Linus Torvalds. In questa fase potrebbero emergere nuovi problemi e/o + commenti; è importante che lo sviluppatore sia collaborativo e che sistemi + ogni questione che possa emergere. + + - Rilascio stabile. Ora, il numero di utilizzatori che sono potenzialmente + toccati dalla patch è aumentato, quindi, ancora una volta, potrebbero + emergere nuovi problemi. + + - Manutenzione di lungo periodo. Nonostante sia possibile che uno sviluppatore + si dimentichi del codice dopo la sua integrazione, questo comportamento + lascia una brutta impressione nella comunità di sviluppo. Integrare il + codice elimina alcuni degli oneri facenti parte della manutenzione, in + particolare, sistemerà le problematiche causate dalle modifiche all'API. + Ma lo sviluppatore originario dovrebbe continuare ad assumersi la + responsabilità per il codice se quest'ultimo continua ad essere utile + nel lungo periodo. + +Uno dei più grandi errori fatti dagli sviluppatori kernel (o dai loro datori +di lavoro) è quello di cercare di ridurre tutta la procedura ad una singola +"integrazione nel remo principale". Questo approccio inevitabilmente conduce +a una condizione di frustrazione per tutti coloro che sono coinvolti. + +Come le modifiche finiscono nel Kernel +-------------------------------------- + +Esiste una sola persona che può inserire le patch nel repositorio principale +del kernel: Linus Torvalds. Ma, per esempio, di tutte le 9500 patch +che entrarono nella versione 2.6.38 del kernel, solo 112 (circa +l'1,3%) furono scelte direttamente da Linus in persona. Il progetto +del kernel è cresciuto fino a raggiungere una dimensione tale per cui +un singolo sviluppatore non può controllare e selezionare +indipendentemente ogni modifica senza essere supportato. La via +scelta dagli sviluppatori per indirizzare tale crescita è stata quella +di utilizzare un sistema di "sottotenenti" basato sulla fiducia. + +Il codice base del kernel è spezzato in una serie si sottosistemi: rete, +supporto per specifiche architetture, gestione della memoria, video e +strumenti, etc. Molti sottosistemi hanno un manutentore designato: ovvero uno +sviluppatore che ha piena responsabilità di tutto il codice presente in quel +sottosistema. Tali manutentori di sottosistema sono i guardiani +(in un certo senso) della parte di kernel che gestiscono; sono coloro che +(solitamente) accetteranno una patch per l'inclusione nel ramo principale +del kernel. + +I manutentori di sottosistema gestiscono ciascuno la propria parte dei sorgenti +del kernel, utilizzando abitualmente (ma certamente non sempre) git. +Strumenti come git (e affini come quilt o mercurial) permettono ai manutentori +di stilare una lista delle patch, includendo informazioni sull'autore ed +altri metadati. In ogni momento, il manutentore può individuare quale patch +nel sua repositorio non si trova nel ramo principale. + +Quando la "finestra di integrazione" si apre, i manutentori di alto livello +chiederanno a Linus di "prendere" dai loro repositori le modifiche che hanno +selezionato per l'inclusione. Se Linus acconsente, il flusso di patch si +convoglierà nel repositorio di quest ultimo, divenendo così parte del ramo +principale del kernel. La quantità d'attenzione che Linus presta alle +singole patch ricevute durante l'operazione di integrazione varia. +È chiaro che, qualche volta, guardi più attentamente. Ma, come regola +generale, Linus confida nel fatto che i manutentori di sottosistema non +selezionino pessime patch. + +I manutentori di sottosistemi, a turno, possono "prendere" patch +provenienti da altri manutentori. Per esempio, i sorgenti per la rete rete +sono costruiti da modifiche che si sono accumulate inizialmente nei sorgenti +dedicati ai driver per dispositivi di rete, rete senza fili, ecc. Tale +catena di repositori può essere più o meno lunga, benché raramente ecceda +i due o tre collegamenti. Questo processo è conosciuto come +"la catena della fiducia", perché ogni manutentore all'interno della +catena si fida di coloro che gestiscono i livelli più bassi. + +Chiaramente, in un sistema come questo, l'inserimento delle patch all'interno +del kernel si basa sul trovare il manutentore giusto. Di norma, inviare +patch direttamente a Linus non è la via giusta. + + +Sorgenti -next +-------------- + +La catena di sottosistemi guida il flusso di patch all'interno del kernel, +ma solleva anche un interessante quesito: se qualcuno volesse vedere tutte le +patch pronte per la prossima finestra di integrazione? +Gli sviluppatori si interesseranno alle patch in sospeso per verificare +che non ci siano altri conflitti di cui preoccuparsi; una modifica che, per +esempio, cambia il prototipo di una funzione fondamentale del kernel andrà in +conflitto con qualsiasi altra modifica che utilizzi la vecchia versione di +quella funzione. Revisori e tester vogliono invece avere accesso alle +modifiche nella loro totalità prima che approdino nel ramo principale del +kernel. Uno potrebbe prendere le patch provenienti da tutti i sottosistemi +d'interesse, ma questo sarebbe un lavoro enorme e fallace. + +La risposta ci viene sotto forma di sorgenti -next, dove i sottosistemi sono +raccolti per essere testati e controllati. Il più vecchio di questi sorgenti, +gestito da Andrew Morton, è chiamato "-mm" (memory management, che è l'inizio +di tutto). L'-mm integra patch proveniente da una lunga lista di sottosistemi; +e ha, inoltre, alcune patch destinate al supporto del debugging. + +Oltre a questo, -mm contiene una raccolta significativa di patch che sono +state selezionate da Andrew direttamente. Queste patch potrebbero essere +state inviate in una lista di discussione, o possono essere applicate ad una +parte del kernel per la quale non esiste un sottosistema dedicato. +Di conseguenza, -mm opera come una specie di sottosistema "ultima spiaggia"; +se per una patch non esiste una via chiara per entrare nel ramo principale, +allora è probabile che finirà in -mm. Le patch passate per -mm +eventualmente finiranno nel sottosistema più appropriato o saranno inviate +direttamente a Linus. In un tipico ciclo di sviluppo, circa il 5-10% delle +patch andrà nel ramo principale attraverso -mm. + +La patch -mm correnti sono disponibili nella cartella "mmotm" (-mm of +the moment) all'indirizzo: + + http://www.ozlabs.org/~akpm/mmotm/ + +È molto probabile che l'uso dei sorgenti MMOTM diventi un'esperienza +frustrante; ci sono buone probabilità che non compili nemmeno. + +I sorgenti principali per il prossimo ciclo d'integrazione delle patch +è linux-next, gestito da Stephen Rothwell. I sorgenti linux-next sono, per +definizione, un'istantanea di come dovrà apparire il ramo principale dopo che +la prossima finestra di inclusione si chiuderà. I linux-next sono annunciati +sulla lista di discussione linux-kernel e linux-next nel momento in cui +vengono assemblati; e possono essere scaricate da: + + http://www.kernel.org/pub/linux/kernel/next/ + +Linux-next è divenuto parte integrante del processo di sviluppo del kernel; +tutte le patch incorporate durante una finestra di integrazione dovrebbero +aver trovato la propria strada in linux-next, a volte anche prima dell'apertura +della finestra di integrazione. + + +Sorgenti in preparazione +------------------------ + +Nei sorgenti del kernel esiste la cartella drivers/staging/, dove risiedono +molte sotto-cartelle per i driver o i filesystem che stanno per essere aggiunti +al kernel. Questi restano nella cartella drivers/staging fintanto che avranno +bisogno di maggior lavoro; una volta completato, possono essere spostate +all'interno del kernel nel posto più appropriato. Questo è il modo di tener +traccia dei driver che non sono ancora in linea con gli standard di codifica +o qualità, ma che le persone potrebbero voler usare ugualmente e tracciarne +lo sviluppo. + +Greg Kroah-Hartman attualmente gestisce i sorgenti in preparazione. I driver +che non sono completamente pronti vengono inviati a lui, e ciascun driver avrà +la propria sotto-cartella in drivers/staging/. Assieme ai file sorgenti +dei driver, dovrebbe essere presente nella stessa cartella anche un file TODO. +Il file TODO elenca il lavoro ancora da fare su questi driver per poter essere +accettati nel kernel, e indica anche la lista di persone da inserire in copia +conoscenza per ogni modifica fatta. Le regole attuali richiedono che i +driver debbano, come minimo, compilare adeguatamente. + +La *preparazione* può essere una via relativamente facile per inserire nuovi +driver all'interno del ramo principale, dove, con un po' di fortuna, saranno +notati da altri sviluppatori e migliorati velocemente. Entrare nella fase +di preparazione non è però la fine della storia, infatti, il codice che si +trova nella cartella staging che non mostra regolari progressi potrebbe +essere rimosso. Le distribuzioni, inoltre, tendono a dimostrarsi relativamente +riluttanti nell'attivare driver in preparazione. Quindi lo preparazione è, +nel migliore dei casi, una tappa sulla strada verso il divenire un driver +del ramo principale. + + +Strumenti +--------- + +Come è possibile notare dal testo sopra, il processo di sviluppo del kernel +dipende pesantemente dalla capacità di guidare la raccolta di patch in +diverse direzioni. L'intera cosa non funzionerebbe se non venisse svolta +con l'uso di strumenti appropriati e potenti. Spiegare l'uso di tali +strumenti non è lo scopo di questo documento, ma c'è spazio per alcuni +consigli. + +In assoluto, nella comunità del kernel, predomina l'uso di git come sistema +di gestione dei sorgenti. Git è una delle diverse tipologie di sistemi +distribuiti di controllo versione che sono stati sviluppati nella comunità +del software libero. Esso è calibrato per lo sviluppo del kernel, e si +comporta abbastanza bene quando ha a che fare con repositori grandi e con un +vasto numero di patch. Git ha inoltre la reputazione di essere difficile +da imparare e utilizzare, benché stia migliorando. Agli sviluppatori +del kernel viene richiesta un po' di familiarità con git; anche se non lo +utilizzano per il proprio lavoro, hanno bisogno di git per tenersi al passo +con il lavoro degli altri sviluppatori (e con il ramo principale). + +Git è ora compreso in quasi tutte le distribuzioni Linux. Esiste una sito che +potete consultare: + + http://git-scm.com/ + +Qui troverete i riferimenti alla documentazione e alle guide passo-passo. + +Tra gli sviluppatori Kernel che non usano git, la scelta alternativa più +popolare è quasi sicuramente Mercurial: + + http://www.selenic.com/mercurial/ + +Mercurial condivide diverse caratteristiche con git, ma fornisce +un'interfaccia che potrebbe risultare più semplice da utilizzare. + +L'altro strumento che vale la pena conoscere è Quilt: + + http://savannah.nongnu.org/projects/quilt/ + + +Quilt è un sistema di gestione delle patch, piuttosto che un sistema +di gestione dei sorgenti. Non mantiene uno storico degli eventi; ma piuttosto +è orientato verso il tracciamento di uno specifico insieme di modifiche +rispetto ad un codice in evoluzione. Molti dei più grandi manutentori di +sottosistema utilizzano quilt per gestire le patch che dovrebbero essere +integrate. Per la gestione di certe tipologie di sorgenti (-mm, per esempio), +quilt è il miglior strumento per svolgere il lavoro. + + +Liste di discussione +-------------------- + +Una grossa parte del lavoro di sviluppo del Kernel Linux viene svolto tramite +le liste di discussione. È difficile essere un membro della comunità +pienamente coinvolto se non si partecipa almeno ad una lista da qualche +parte. Ma, le liste di discussione di Linux rappresentano un potenziale +problema per gli sviluppatori, che rischiano di venir sepolti da un mare di +email, restare incagliati nelle convenzioni in vigore nelle liste Linux, +o entrambi. + +Molte delle liste di discussione del Kernel girano su vger.kernel.org; +l'elenco principale lo si trova sul sito: + + http://vger.kernel.org/vger-lists.html + +Esistono liste gestite altrove; un certo numero di queste sono in +redhat.com/mailman/listinfo. + +La lista di discussione principale per lo sviluppo del kernel è, ovviamente, +linux-kernel. Questa lista è un luogo ostile dove trovarsi; i volumi possono +raggiungere i 500 messaggi al giorno, la quantità di "rumore" è elevata, +la conversazione può essere strettamente tecnica e i partecipanti non sono +sempre preoccupati di mostrare un alto livello di educazione. Ma non esiste +altro luogo dove la comunità di sviluppo del kernel si unisce per intero; +gli sviluppatori che evitano tale lista si perderanno informazioni importanti. + +Ci sono alcuni consigli che possono essere utili per sopravvivere a +linux-kernel: + +- Tenete la lista in una cartella separata, piuttosto che inserirla nella + casella di posta principale. Così da essere in grado di ignorare il flusso + di mail per un certo periodo di tempo. + +- Non cercate di seguire ogni conversazione - nessuno lo fa. È importante + filtrare solo gli argomenti d'interesse (sebbene va notato che le + conversazioni di lungo periodo possono deviare dall'argomento originario + senza cambiare il titolo della mail) e le persone che stanno partecipando. + +- Non alimentate i troll. Se qualcuno cerca di creare nervosismo, ignoratelo. + +- Quando rispondete ad una mail linux-kernel (o ad altre liste) mantenete + tutti i Cc:. In assenza di importanti motivazioni (come una richiesta + esplicita), non dovreste mai togliere destinatari. Assicuratevi sempre che + la persona alla quale state rispondendo sia presente nella lista Cc. Questa + usanza fa si che divenga inutile chiedere esplicitamente di essere inseriti + in copia nel rispondere al vostro messaggio. + +- Cercate nell'archivio della lista (e nella rete nella sua totalità) prima + di far domande. Molti sviluppatori possono divenire impazienti con le + persone che chiaramente non hanno svolto i propri compiti a casa. + +- Evitate il *top-posting* (cioè la pratica di mettere la vostra risposta sopra + alla frase alla quale state rispondendo). Ciò renderebbe la vostra risposta + difficile da leggere e genera scarsa impressione. + +- Chiedete nella lista di discussione corretta. Linux-kernel può essere un + punto di incontro generale, ma non è il miglior posto dove trovare + sviluppatori da tutti i sottosistemi. + +Infine, la ricerca della corretta lista di discussione è uno degli errori più +comuni per gli sviluppatori principianti. Qualcuno che pone una domanda +relativa alla rete su linux-kernel riceverà quasi certamente il suggerimento +di chiedere sulla lista netdev, che è la lista frequentata dagli sviluppatori +di rete. Ci sono poi altre liste per i sottosistemi SCSI, video4linux, IDE, +filesystem, etc. Il miglior posto dove cercare una lista di discussione è il +file MAINTAINERS che si trova nei sorgenti del kernel. + +Iniziare con lo sviluppo del Kernel +----------------------------------- + +Sono comuni le domande sul come iniziare con lo sviluppo del kernel - sia da +singole persone che da aziende. Altrettanto comuni sono i passi falsi che +rendono l'inizio di tale relazione più difficile di quello che dovrebbe essere. + +Le aziende spesso cercano di assumere sviluppatori noti per creare un gruppo +di sviluppo iniziale. Questo, in effetti, può essere una tecnica efficace. +Ma risulta anche essere dispendiosa e non va ad accrescere il bacino di +sviluppatori kernel con esperienza. È possibile anche "portare a casa" +sviluppatori per accelerare lo sviluppo del kernel, dando comunque +all'investimento un po' di tempo. Prendersi questo tempo può fornire +al datore di lavoro un gruppo di sviluppatori che comprendono sia il kernel +che l'azienda stessa, e che possono supportare la formazione di altre persone. +Nel medio periodo, questa è spesso uno delle soluzioni più proficue. + +I singoli sviluppatori sono spesso, comprensibilmente, una perdita come punto +di partenza. Iniziare con un grande progetto può rivelarsi intimidatorio; +spesso all'inizio si vuole solo verificare il terreno con qualcosa di piccolo. +Questa è una delle motivazioni per le quali molti sviluppatori saltano alla +creazione di patch che vanno a sistemare errori di battitura o +problematiche minori legate allo stile del codice. Sfortunatamente, tali +patch creano un certo livello di rumore che distrae l'intera comunità di +sviluppo, quindi, sempre di più, esse vengono degradate. I nuovi sviluppatori +che desiderano presentarsi alla comunità non riceveranno l'accoglienza +che vorrebbero con questi mezzi. + +Andrew Morton da questo consiglio agli aspiranti sviluppatori kernel + +:: + + Il primo progetto per un neofita del kernel dovrebbe essere + sicuramente quello di "assicurarsi che il kernel funzioni alla + perfezione sempre e su tutte le macchine sulle quali potete stendere + la vostra mano". Solitamente il modo per fare ciò è quello di + collaborare con gli altri nel sistemare le cose (questo richiede + persistenza!) ma va bene - è parte dello sviluppo kernel. + +(http://lwn.net/Articles/283982/). + +In assenza di problemi ovvi da risolvere, si consiglia agli sviluppatori +di consultare, in generale, la lista di regressioni e di bachi aperti. +Non c'è mai carenza di problematiche bisognose di essere sistemate; +accollandosi tali questioni gli sviluppatori accumuleranno esperienza con +la procedura, ed allo stesso tempo, aumenteranno la loro rispettabilità +all'interno della comunità di sviluppo. diff --git a/Documentation/translations/it_IT/process/3.Early-stage.rst b/Documentation/translations/it_IT/process/3.Early-stage.rst new file mode 100644 index 000000000..0809de391 --- /dev/null +++ b/Documentation/translations/it_IT/process/3.Early-stage.rst @@ -0,0 +1,242 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/3.Early-stage.rst ` +:Translator: Alessia Mantegazza + +.. _it_development_early_stage: + +I primi passi della pianificazione +================================== + +Osservando un progetto di sviluppo per il kernel Linux, si potrebbe essere +tentati dal saltare tutto e iniziare a codificare. Tuttavia, come ogni +progetto significativo, molta della preparazione per giungere al successo +viene fatta prima che una sola linea di codice venga scritta. Il tempo speso +nella pianificazione e la comunicazione può far risparmiare molto +tempo in futuro. + +Specificare il problema +----------------------- + +Come qualsiasi progetto ingegneristico, un miglioramento del kernel di +successo parte con una chiara descrizione del problema da risolvere. +In alcuni casi, questo passaggio è facile: ad esempio quando un driver è +richiesto per un particolare dispositivo. In altri casi invece, si +tende a confondere il problema reale con le soluzioni proposte e questo +può portare all'emergere di problemi. + +Facciamo un esempio: qualche anno fa, gli sviluppatori che lavoravano con +linux audio cercarono un modo per far girare le applicazioni senza dropouts +o altri artefatti dovuti all'eccessivo ritardo nel sistema. La soluzione +alla quale giunsero fu un modulo del kernel destinato ad agganciarsi al +framework Linux Security Module (LSM); questo modulo poteva essere +configurato per dare ad una specifica applicazione accesso allo +schedulatore *realtime*. Tale modulo fu implementato e inviato nella +lista di discussione linux-kernel, dove incontrò subito dei problemi. + +Per gli sviluppatori audio, questo modulo di sicurezza era sufficiente a +risolvere il loro problema nell'immediato. Per l'intera comunità kernel, +invece, era un uso improprio del framework LSM (che non è progettato per +conferire privilegi a processi che altrimenti non avrebbero potuto ottenerli) +e un rischio per la stabilità del sistema. Le loro soluzioni di punta nel +breve periodo, comportavano un accesso alla schedulazione realtime attraverso +il meccanismo rlimit, e nel lungo periodo un costante lavoro nella riduzione +dei ritardi. + +La comunità audio, comunque, non poteva vedere al di là della singola +soluzione che avevano implementato; erano riluttanti ad accettare alternative. +Il conseguente dissenso lasciò in quegli sviluppatori un senso di +disillusione nei confronti dell'intero processo di sviluppo; uno di loro +scrisse questo messaggio: + + Ci sono numerosi sviluppatori del kernel Linux davvero bravi, ma + rischiano di restare sovrastati da una vasta massa di stolti arroganti. + Cercare di comunicare le richieste degli utenti a queste persone è + una perdita di tempo. Loro sono troppo "intelligenti" per stare ad + ascoltare dei poveri mortali. + + (http://lwn.net/Articles/131776/). + +La realtà delle cose fu differente; gli sviluppatori del kernel erano molto +più preoccupati per la stabilità del sistema, per la manutenzione di lungo +periodo e cercavano la giusta soluzione alla problematica esistente con uno +specifico modulo. La morale della storia è quella di concentrarsi sul +problema - non su di una specifica soluzione- e di discuterne con la comunità +di sviluppo prima di investire tempo nella scrittura del codice. + +Quindi, osservando un progetto di sviluppo del kernel, si dovrebbe +rispondere a questa lista di domande: + +- Qual'è, precisamente, il problema che dev'essere risolto? + +- Chi sono gli utenti coinvolti da tal problema? A quale caso dovrebbe + essere indirizzata la soluzione? + +- In che modo il kernel risulta manchevole nell'indirizzare il problema + in questione? + +Solo dopo ha senso iniziare a considerare le possibili soluzioni. + +Prime discussioni +----------------- + +Quando si pianifica un progetto di sviluppo per il kernel, sarebbe quanto meno +opportuno discuterne inizialmente con la comunità prima di lanciarsi +nell'implementazione. Una discussione preliminare può far risparmiare sia +tempo che problemi in svariati modi: + + - Potrebbe essere che il problema sia già stato risolto nel kernel in + una maniera che non avete ancora compreso. Il kernel Linux è grande e ha + una serie di funzionalità e capacità che non sono scontate nell'immediato. + Non tutte le capacità del kernel sono documentate così bene come ci + piacerebbe, ed è facile perdersi qualcosa. Il vostro autore ha assistito + alla pubblicazione di un driver intero che duplica un altro driver + esistente di cui il nuovo autore era ignaro. Il codice che rinnova + ingranaggi già esistenti non è soltanto dispendioso; non verrà nemmeno + accettato nel ramo principale del kernel. + + - Potrebbero esserci proposte che non sono considerate accettabili per + l'integrazione all'interno del ramo principale. È meglio affrontarle + prima di scrivere il codice. + + - È possibile che altri sviluppatori abbiano pensato al problema; potrebbero + avere delle idee per soluzioni migliori, e potrebbero voler contribuire + alla loro creazione. + +Anni di esperienza con la comunità di sviluppo del kernel hanno impartito una +chiara lezione: il codice per il kernel che è pensato e sviluppato a porte +chiuse, inevitabilmente, ha problematiche che si rivelano solo quando il +codice viene rilasciato pubblicamente. Qualche volta tali problemi sono +importanti e richiedono mesi o anni di sforzi prima che il codice possa +raggiungere gli standard richiesti della comunità. +Alcuni esempi possono essere: + + - La rete Devicescape è stata creata e implementata per sistemi + mono-processore. Non avrebbe potuto essere inserita nel ramo principale + fino a che non avesse supportato anche i sistemi multi-processore. + Riadattare i meccanismi di sincronizzazione e simili è un compito difficile; + come risultato, l'inserimento di questo codice (ora chiamato mac80211) + fu rimandato per più di un anno. + + - Il filesystem Reiser4 include una seria di funzionalità che, secondo + l'opinione degli sviluppatori principali del kernel, avrebbero dovuto + essere implementate a livello di filesystem virtuale. Comprende + anche funzionalità che non sono facilmente implementabili senza esporre + il sistema al rischio di uno stallo. La scoperta tardiva di questi + problemi - e il diniego a risolverne alcuni - ha avuto come conseguenza + il fatto che Raiser4 resta fuori dal ramo principale del kernel. + + - Il modulo di sicurezza AppArmor utilizzava strutture dati del + filesystem virtuale interno in modi che sono stati considerati rischiosi e + inattendibili. Questi problemi (tra le altre cose) hanno tenuto AppArmor + fuori dal ramo principale per anni. + +Ciascuno di questi casi è stato un travaglio e ha richiesto del lavoro +straordinario, cose che avrebbero potuto essere evitate con alcune +"chiacchierate" preliminari con gli sviluppatori kernel. + +Con chi parlare? +---------------- + +Quando gli sviluppatori hanno deciso di rendere pubblici i propri progetti, la +domanda successiva sarà: da dove partiamo? La risposta è quella di trovare +la giusta lista di discussione e il giusto manutentore. Per le liste di +discussione, il miglior approccio è quello di cercare la lista più adatta +nel file MAINTAINERS. Se esiste una lista di discussione di sottosistema, +è preferibile pubblicare lì piuttosto che sulla lista di discussione generale +del kernel Linux; avrete maggiori probabilità di trovare sviluppatori con +esperienza sul tema, e l'ambiente che troverete potrebbe essere più +incoraggiante. + +Trovare manutentori può rivelarsi un po' difficoltoso. Ancora, il file +MAINTAINERS è il posto giusto da dove iniziare. Il file potrebbe non essere +sempre aggiornato, inoltre, non tutti i sottosistemi sono rappresentati qui. +Coloro che sono elencati nel file MAINTAINERS potrebbero, in effetti, non +essere le persone che attualmente svolgono quel determinato ruolo. Quindi, +quando c'è un dubbio su chi contattare, un trucco utile è quello di usare +git (git log in particolare) per vedere chi attualmente è attivo all'interno +del sottosistema interessato. Controllate chi sta scrivendo le patch, +e chi, se non ci fosse nessuno, sta aggiungendo la propria firma +(Signed-off-by) a quelle patch. Quelle sono le persone maggiormente +qualificate per aiutarvi con lo sviluppo di nuovo progetto. + +Il compito di trovare il giusto manutentore, a volte, è una tale sfida che +ha spinto gli sviluppatori del kernel a scrivere uno script che li aiutasse +in questa ricerca: + +:: + + .../scripts/get_maintainer.pl + +Se questo script viene eseguito con l'opzione "-f" ritornerà il manutentore(i) +attuale per un dato file o cartella. Se viene passata una patch sulla linea di +comando, lo script elencherà i manutentori che dovrebbero riceverne una copia. +Questo è la maniera raccomandata (non quella con "-f") per ottenere la lista di +persone da aggiungere a Cc per le vostre patch. Ci sono svariate opzioni che +regolano quanto a fondo get_maintainer.pl debba cercare i manutentori; siate +quindi prudenti nell'utilizzare le opzioni più aggressive poiché potreste finire +per includere sviluppatori che non hanno un vero interesse per il codice che +state modificando. + +Se tutto ciò dovesse fallire, parlare con Andrew Morton potrebbe essere +un modo efficace per capire chi è il manutentore di un dato pezzo di codice. + +Quando pubblicare +----------------- + +Se potete, pubblicate i vostri intenti durante le fasi preliminari, sarà +molto utile. Descrivete il problema da risolvere e ogni piano che è stato +elaborato per l'implementazione. Ogni informazione fornita può aiutare +la comunità di sviluppo a fornire spunti utili per il progetto. + +Un evento che potrebbe risultare scoraggiate e che potrebbe accadere in +questa fase non è il ricevere una risposta ostile, ma, invece, ottenere +una misera o inesistente reazione. La triste verità è che: (1) gli +sviluppatori del kernel tendono ad essere occupati, (2) ci sono tante persone +con grandi progetti e poco codice (o anche solo la prospettiva di +avere un codice) a cui riferirsi e (3) nessuno è obbligato a revisionare +o a fare osservazioni in merito ad idee pubblicate da altri. Oltre a +questo, progetti di alto livello spesso nascondono problematiche che si +rivelano solo quando qualcuno cerca di implementarle; per questa ragione +gli sviluppatori kernel preferirebbero vedere il codice. + +Quindi, se una richiesta pubblica di commenti riscuote poco successo, non +pensate che ciò significhi che non ci sia interesse nel progetto. +Sfortunatamente, non potete nemmeno assumere che non ci siano problemi con +la vostra idea. La cosa migliore da fare in questa situazione è quella di +andare avanti e tenere la comunità informata mentre procedete. + +Ottenere riscontri ufficiali +---------------------------- + +Se il vostro lavoro è stato svolto in un ambiente aziendale - come molto +del lavoro fatto su Linux - dovete, ovviamente, avere il permesso dei +dirigenti prima che possiate pubblicare i progetti, o il codice aziendale, +su una lista di discussione pubblica. La pubblicazione di codice che non +è stato rilascio espressamente con licenza GPL-compatibile può rivelarsi +problematico; prima la dirigenza, e il personale legale, troverà una decisione +sulla pubblicazione di un progetto, meglio sarà per tutte le persone coinvolte. + +A questo punto, alcuni lettori potrebbero pensare che il loro lavoro sul +kernel è preposto a supportare un prodotto che non è ancora ufficialmente +riconosciuto. Rivelare le intenzioni dei propri datori di lavori in una +lista di discussione pubblica potrebbe non essere una soluzione valida. +In questi casi, vale la pena considerare se la segretezza sia necessaria +o meno; spesso non c'è una reale necessità di mantenere chiusi i progetti di +sviluppo. + +Detto ciò, ci sono anche casi dove l'azienda legittimamente non può rivelare +le proprie intenzioni in anticipo durante il processo di sviluppo. Le aziende +che hanno sviluppatori kernel esperti possono scegliere di procedere a +carte coperte partendo dall'assunto che saranno in grado di evitare, o gestire, +in futuro, eventuali problemi d'integrazione. Per le aziende senza questo tipo +di esperti, la migliore opzione è spesso quella di assumere uno sviluppatore +esterno che revisioni i progetti con un accordo di segretezza. +La Linux Foundation applica un programma di NDA creato appositamente per +aiutare le aziende in questa particolare situazione; potrete trovare più +informazioni sul sito: + + http://www.linuxfoundation.org/en/NDA_program + +Questa tipologia di revisione è spesso sufficiente per evitare gravi problemi +senza che sia richiesta l'esposizione pubblica del progetto. diff --git a/Documentation/translations/it_IT/process/4.Coding.rst b/Documentation/translations/it_IT/process/4.Coding.rst new file mode 100644 index 000000000..54fd255b7 --- /dev/null +++ b/Documentation/translations/it_IT/process/4.Coding.rst @@ -0,0 +1,446 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/4.Coding.rst ` +:Translator: Alessia Mantegazza + +.. _it_development_coding: + +Scrivere codice corretto +======================== + +Nonostante ci sia molto da dire sul processo di creazione, sulla sua solidità +e sul suo orientamento alla comunità, la prova di ogni progetto di sviluppo +del kernel si trova nel codice stesso. È il codice che sarà esaminato dagli +altri sviluppatori ed inserito (o no) nel ramo principale. Quindi è la +qualità di questo codice che determinerà il successo finale del progetto. + +Questa sezione esaminerà il processo di codifica. Inizieremo con uno sguardo +sulle diverse casistiche nelle quali gli sviluppatori kernel possono +sbagliare. Poi, l'attenzione si sposterà verso "il fare le cose +correttamente" e sugli strumenti che possono essere utili in questa missione. + +Trappole +-------- + +Lo stile del codice +******************* + +Il kernel ha da tempo delle norme sullo stile di codifica che sono descritte in +:ref:`Documentation/translations/it_IT/process/coding-style.rst `. +Per la maggior parte del tempo, la politica descritta in quel file è stata +praticamente informativa. Ne risulta che ci sia una quantità sostanziale di +codice nel kernel che non rispetta le linee guida relative allo stile. +La presenza di quel codice conduce a due distinti pericoli per gli +sviluppatori kernel. + +Il primo di questi è credere che gli standard di codifica del kernel +non sono importanti e possono non essere applicati. La verità è che +aggiungere nuovo codice al kernel è davvero difficile se questo non +rispetta le norme; molti sviluppatori richiederanno che il codice sia +riformulato prima che anche solo lo revisionino. Una base di codice larga +quanto il kernel richiede una certa uniformità, in modo da rendere possibile +per gli sviluppatori una comprensione veloce di ogni sua parte. Non ci sono, +quindi, più spazi per un codice formattato alla carlona. + +Occasionalmente, lo stile di codifica del kernel andrà in conflitto con lo +stile richiesto da un datore di lavoro. In alcuni casi, lo stile del kernel +dovrà prevalere prima che il codice venga inserito. Mettere il codice +all'interno del kernel significa rinunciare a un certo grado di controllo +in differenti modi - incluso il controllo sul come formattare il codice. + +L’altra trappola è quella di pensare che il codice già presente nel kernel +abbia urgentemente bisogno di essere sistemato. Gli sviluppatori potrebbero +iniziare a generare patch che correggono lo stile come modo per prendere +famigliarità con il processo, o come modo per inserire i propri nomi nei +changelog del kernel – o entrambe. La comunità di sviluppo vede un attività +di codifica puramente correttiva come "rumore"; queste attività riceveranno +una fredda accoglienza. Di conseguenza è meglio evitare questo tipo di patch. +Mentre si lavora su un pezzo di codice è normale correggerne anche lo stile, +ma le modifiche di stile non dovrebbero essere fatte fini a se stesse. + +Il documento sullo stile del codice non dovrebbe essere letto come una legge +assoluta che non può mai essere trasgredita. Se c’è un a buona ragione +(per esempio, una linea che diviene poco leggibile se divisa per rientrare +nel limite di 80 colonne), fatelo e basta. + +Notate che potete utilizzare lo strumento “clang-format” per aiutarvi con +le regole, per una riformattazione automatica e veloce del vostro codice +e per revisionare interi file per individuare errori nello stile di codifica, +refusi e possibili miglioramenti. Inoltre è utile anche per classificare gli +``#includes``, per allineare variabili/macro, per testi derivati ed altri +compiti del genere. Consultate il file +:ref:`Documentation/translations/it_IT/process/clang-format.rst ` +per maggiori dettagli + + +Livelli di astrazione +********************* + + +I professori di Informatica insegnano ai propri studenti a fare ampio uso dei +livelli di astrazione nel nome della flessibilità e del nascondere informazioni. +Certo il kernel fa un grande uso dell'astrazione; nessun progetto con milioni +di righe di codice potrebbe fare altrimenti e sopravvivere. Ma l'esperienza +ha dimostrato che un'eccessiva o prematura astrazione può rivelarsi dannosa +al pari di una prematura ottimizzazione. L'astrazione dovrebbe essere usata +fino al livello necessario e non oltre. + +Ad un livello base, considerate una funzione che ha un argomento che viene +sempre impostato a zero da tutti i chiamanti. Uno potrebbe mantenere +quell'argomento nell'eventualità qualcuno volesse sfruttare la flessibilità +offerta. In ogni caso, tuttavia, ci sono buone possibilità che il codice +che va ad implementare questo argomento aggiuntivo, sia stato rotto in maniera +sottile, in un modo che non è mai stato notato - perché non è mai stato usato. +Oppure, quando sorge la necessità di avere più flessibilità, questo argomento +non la fornisce in maniera soddisfacente. Gli sviluppatori di Kernel, +sottopongono costantemente patch che vanno a rimuovere gli argomenti +inutilizzate; anche se, in generale, non avrebbero dovuto essere aggiunti. + +I livelli di astrazione che nascondono l'accesso all'hardware - +spesso per poter usare dei driver su diversi sistemi operativi - vengono +particolarmente disapprovati. Tali livelli oscurano il codice e possono +peggiorare le prestazioni; essi non appartengono al kernel Linux. + +D'altro canto, se vi ritrovate a dover copiare una quantità significativa di +codice proveniente da un altro sottosistema del kernel, è tempo di chiedersi +se, in effetti, non avrebbe più senso togliere parte di quel codice e metterlo +in una libreria separata o di implementare quella funzionalità ad un livello +più elevato. Non c'è utilità nel replicare lo stesso codice per tutto +il kernel. + + +#ifdef e l'uso del preprocessore in generale +******************************************** + +Il preprocessore C sembra essere una fonte di attrazione per qualche +programmatore C, che ci vede una via per ottenere una grande flessibilità +all'interno di un file sorgente. Ma il preprocessore non è scritto in C, +e un suo massiccio impiego conduce a un codice che è molto più difficile +da leggere per gli altri e che rende più difficile il lavoro di verifica del +compilatore. L'uso eccessivo del preprocessore è praticamente sempre il segno +di un codice che necessita di un certo lavoro di pulizia. + +La compilazione condizionata con #ifdef è, in effetti, un potente strumento, +ed esso viene usato all'interno del kernel. Ma esiste un piccolo desiderio: +quello di vedere il codice coperto solo da una leggera spolverata di +blocchi #ifdef. Come regola generale, quando possibile, l'uso di #ifdef +dovrebbe essere confinato nei file d'intestazione. Il codice compilato +condizionatamente può essere confinato a funzioni tali che, nel caso in cui +il codice non deve essere presente, diventano vuote. Il compilatore poi +ottimizzerà la chiamata alla funzione vuota rimuovendola. Il risultato è +un codice molto più pulito, più facile da seguire. + +Le macro del preprocessore C presentano una serie di pericoli, inclusi +valutazioni multiple di espressioni che hanno effetti collaterali e non +garantiscono una sicurezza rispetto ai tipi. Se siete tentati dal definire +una macro, considerate l'idea di creare invece una funzione inline. Il codice +che ne risulterà sarà lo stesso, ma le funzioni inline sono più leggibili, +non considerano i propri argomenti più volte, e permettono al compilatore di +effettuare controlli sul tipo degli argomenti e del valore di ritorno. + + +Funzioni inline +*************** + +Comunque, anche le funzioni inline hanno i loro pericoli. I programmatori +potrebbero innamorarsi dell'efficienza percepita derivata dalla rimozione +di una chiamata a funzione. Queste funzioni, tuttavia, possono ridurre le +prestazioni. Dato che il loro codice viene replicato ovunque vi sia una +chiamata ad esse, si finisce per gonfiare le dimensioni del kernel compilato. +Questi, a turno, creano pressione sulla memoria cache del processore, e questo +può causare rallentamenti importanti. Le funzioni inline, di norma, dovrebbero +essere piccole e usate raramente. Il costo di una chiamata a funzione, dopo +tutto, non è così alto; la creazione di molte funzioni inline è il classico +esempio di un'ottimizzazione prematura. + +In generale, i programmatori del kernel ignorano gli effetti della cache a +loro rischio e pericolo. Il classico compromesso tempo/spazio teorizzato +all'inizio delle lezioni sulle strutture dati spesso non si applica +all'hardware moderno. Lo spazio *è* tempo, in questo senso un programma +più grande sarà più lento rispetto ad uno più compatto. + +I compilatori più recenti hanno preso un ruolo attivo nel decidere se +una data funzione deve essere resa inline oppure no. Quindi l'uso +indiscriminato della parola chiave "inline" potrebbe non essere non solo +eccessivo, ma anche irrilevante. + +Sincronizzazione +**************** + +Nel maggio 2006, il sistema di rete "Devicescape" fu rilasciato in pompa magna +sotto la licenza GPL e reso disponibile per la sua inclusione nella ramo +principale del kernel. Questa donazione fu una notizia bene accolta; +il supporto per le reti senza fili era considerata, nel migliore dei casi, +al di sotto degli standard; il sistema Deviscape offrì la promessa di una +risoluzione a tale situazione. Tuttavia, questo codice non fu inserito nel +ramo principale fino al giugno del 2007 (2.6.22). Cosa accadde? + +Quel codice mostrava numerosi segnali di uno sviluppo in azienda avvenuto +a porte chiuse. Ma in particolare, un grosso problema fu che non fu +progettato per girare in un sistema multiprocessore. Prima che questo +sistema di rete (ora chiamato mac80211) potesse essere inserito, fu necessario +un lavoro sugli schemi di sincronizzazione. + +Una volta, il codice del kernel Linux poteva essere sviluppato senza pensare +ai problemi di concorrenza presenti nei sistemi multiprocessore. Ora, +comunque, questo documento è stato scritto su di un portatile dual-core. +Persino su sistemi a singolo processore, il lavoro svolto per incrementare +la capacità di risposta aumenterà il livello di concorrenza interno al kernel. +I giorni nei quali il codice poteva essere scritto senza pensare alla +sincronizzazione sono da passati tempo. + +Ogni risorsa (strutture dati, registri hardware, etc.) ai quali si potrebbe +avere accesso simultaneo da più di un thread deve essere sincronizzato. Il +nuovo codice dovrebbe essere scritto avendo tale accortezza in testa; +riadattare la sincronizzazione a posteriori è un compito molto più difficile. +Gli sviluppatori del kernel dovrebbero prendersi il tempo di comprendere bene +le primitive di sincronizzazione, in modo da sceglier lo strumento corretto +per eseguire un compito. Il codice che presenta una mancanza di attenzione +alla concorrenza avrà un percorso difficile all'interno del ramo principale. + +Regressioni +*********** + +Vale la pena menzionare un ultimo pericolo: potrebbe rivelarsi accattivante +l'idea di eseguire un cambiamento (che potrebbe portare a grandi +miglioramenti) che porterà ad alcune rotture per gli utenti esistenti. +Questa tipologia di cambiamento è chiamata "regressione", e le regressioni son +diventate mal viste nel ramo principale del kernel. Con alcune eccezioni, +i cambiamenti che causano regressioni saranno fermati se quest'ultime non +potranno essere corrette in tempo utile. È molto meglio quindi evitare +la regressione fin dall'inizio. + +Spesso si è argomentato che una regressione può essere giustificata se essa +porta risolve più problemi di quanti non ne crei. Perché, dunque, non fare +un cambiamento se questo porta a nuove funzionalità a dieci sistemi per +ognuno dei quali esso determina una rottura? La migliore risposta a questa +domanda ci è stata fornita da Linus nel luglio 2007: + +:: + Dunque, noi non sistemiamo bachi introducendo nuovi problemi. Quella + via nasconde insidie, e nessuno può sapere del tutto se state facendo + dei progressi reali. Sono due passi avanti e uno indietro, oppure + un passo avanti e due indietro? + +(http://lwn.net/Articles/243460/). + +Una particolare tipologia di regressione mal vista consiste in una qualsiasi +sorta di modifica all'ABI dello spazio utente. Una volta che un'interfaccia +viene esportata verso lo spazio utente, dev'essere supportata all'infinito. +Questo fatto rende la creazione di interfacce per lo spazio utente +particolarmente complicato: dato che non possono venir cambiate introducendo +incompatibilità, esse devono essere fatte bene al primo colpo. Per questa +ragione sono sempre richieste: ampie riflessioni, documentazione chiara e +ampie revisioni dell'interfaccia verso lo spazio utente. + + +Strumenti di verifica del codice +-------------------------------- +Almeno per ora la scrittura di codice priva di errori resta un ideale +irraggiungibile ai più. Quello che speriamo di poter fare, tuttavia, è +trovare e correggere molti di questi errori prima che il codice entri nel +ramo principale del kernel. A tal scopo gli sviluppatori del kernel devono +mettere insieme una schiera impressionante di strumenti che possano +localizzare automaticamente un'ampia varietà di problemi. Qualsiasi problema +trovato dal computer è un problema che non affliggerà l'utente in seguito, +ne consegue che gli strumenti automatici dovrebbero essere impiegati ovunque +possibile. + +Il primo passo consiste semplicemente nel fare attenzione agli avvertimenti +proveniente dal compilatore. Versioni moderne di gcc possono individuare +(e segnalare) un gran numero di potenziali errori. Molto spesso, questi +avvertimenti indicano problemi reali. Di regola, il codice inviato per la +revisione non dovrebbe produrre nessun avvertimento da parte del compilatore. +Per mettere a tacere gli avvertimenti, cercate di comprenderne le cause reali +e cercate di evitare le "riparazioni" che fan sparire l'avvertimento senza +però averne trovato la causa. + +Tenete a mente che non tutti gli avvertimenti sono disabilitati di default. +Costruite il kernel con "make KCFLAGS=-W" per ottenerli tutti. + +Il kernel fornisce differenti opzioni che abilitano funzionalità di debugging; +molti di queste sono trovano all'interno del sotto menu "kernel hacking". +La maggior parte di queste opzioni possono essere attivate per qualsiasi +kernel utilizzato per lo sviluppo o a scopo di test. In particolare dovreste +attivare: + + - FRAME_WARN per ottenere degli avvertimenti su stack frame più + grandi di un dato valore. Il risultato generato da questi + avvertimenti può risultare verboso, ma non bisogna preoccuparsi per + gli avvertimenti provenienti da altre parti del kernel. + + - DEBUG_OBJECTS aggiungerà un codice per tracciare il ciclo di vita di + diversi oggetti creati dal kernel e avvisa quando qualcosa viene eseguito + fuori controllo. Se state aggiungendo un sottosistema che crea (ed + esporta) oggetti complessi propri, considerate l'aggiunta di un supporto + al debugging dell'oggetto. + + - DEBUG_SLAB può trovare svariati errori di uso e di allocazione di memoria; + esso dovrebbe esser usato dalla maggior parte dei kernel di sviluppo. + + - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP, e DEBUG_MUTEXES troveranno un certo + numero di errori comuni di sincronizzazione. + +Esistono ancora delle altre opzioni di debugging, di alcune di esse +discuteremo qui sotto. Alcune di esse hanno un forte impatto e non dovrebbero +essere usate tutte le volte. Ma qualche volta il tempo speso nell'capire +le opzioni disponibili porterà ad un risparmio di tempo nel breve termine. + +Uno degli strumenti di debugging più tosti è il *locking checker*, o +"lockdep". Questo strumento traccerà qualsiasi acquisizione e rilascio di +ogni *lock* (spinlock o mutex) nel sistema, l'ordine con il quale i *lock* +sono acquisiti in relazione l'uno con l'altro, l'ambiente corrente di +interruzione, eccetera. Inoltre esso può assicurare che i *lock* vengano +acquisiti sempre nello stesso ordine, che le stesse assunzioni sulle +interruzioni si applichino in tutte le occasioni, e così via. In altre parole, +lockdep può scovare diversi scenari nei quali il sistema potrebbe, in rari +casi, trovarsi in stallo. Questa tipologia di problema può essere grave +(sia per gli sviluppatori che per gli utenti) in un sistema in uso; lockdep +permette di trovare tali problemi automaticamente e in anticipo. + +In qualità di programmatore kernel diligente, senza dubbio, dovrete controllare +il valore di ritorno di ogni operazione (come l'allocazione della memoria) +poiché esso potrebbe fallire. Il nocciolo della questione è che i percorsi +di gestione degli errori, con grande probabilità, non sono mai stati +collaudati del tutto. Il codice collaudato tende ad essere codice bacato; +potrete quindi essere più a vostro agio con il vostro codice se tutti questi +percorsi fossero stati verificati un po' di volte. + +Il kernel fornisce un framework per l'inserimento di fallimenti che fa +esattamente al caso, specialmente dove sono coinvolte allocazioni di memoria. +Con l'opzione per l'inserimento dei fallimenti abilitata, una certa percentuale +di allocazione di memoria sarà destinata al fallimento; questi fallimenti +possono essere ridotti ad uno specifico pezzo di codice. Procedere con +l'inserimento dei fallimenti attivo permette al programmatore di verificare +come il codice risponde quando le cose vanno male. Consultate: +Documentation/fault-injection/fault-injection.rst per avere maggiori +informazioni su come utilizzare questo strumento. + +Altre tipologie di errori possono essere riscontrati con lo strumento di +analisi statica "sparse". Con Sparse, il programmatore può essere avvisato +circa la confusione tra gli indirizzi dello spazio utente e dello spazio +kernel, un miscuglio fra quantità big-endian e little-endian, il passaggio +di un valore intero dove ci sia aspetta un gruppo di flag, e così via. +Sparse deve essere installato separatamente (se il vostra distribuzione non +lo prevede, potete trovarlo su https://sparse.wiki.kernel.org/index.php/Main_Page); +può essere attivato sul codice aggiungendo "C=1" al comando make. + +Lo strumento "Coccinelle" (http://coccinelle.lip6.fr/) è in grado di trovare +una vasta varietà di potenziali problemi di codifica; e può inoltre proporre +soluzioni per risolverli. Un buon numero di "patch semantiche" per il kernel +sono state preparate nella cartella scripts/coccinelle; utilizzando +"make coccicheck" esso percorrerà tali patch semantiche e farà rapporto su +qualsiasi problema trovato. Per maggiori informazioni, consultate +:ref:`Documentation/dev-tools/coccinelle.rst `. + +Altri errori di portabilità sono meglio scovati compilando il vostro codice +per altre architetture. Se non vi accade di avere un sistema S/390 o una +scheda di sviluppo Blackfin sotto mano, potete comunque continuare la fase +di compilazione. Un vasto numero di cross-compilatori per x86 possono +essere trovati al sito: + + http://www.kernel.org/pub/tools/crosstool/ + +Il tempo impiegato nell'installare e usare questi compilatori sarà d'aiuto +nell'evitare situazioni imbarazzanti nel futuro. + + +Documentazione +-------------- + +La documentazione è spesso stata più un'eccezione che una regola nello +sviluppo del kernel. Nonostante questo, un'adeguata documentazione aiuterà +a facilitare l'inserimento di nuovo codice nel kernel, rende la vita più +facile per gli altri sviluppatori e sarà utile per i vostri utenti. In molti +casi, la documentazione è divenuta sostanzialmente obbligatoria. + +La prima parte di documentazione per qualsiasi patch è il suo changelog. +Questi dovrebbero descrivere le problematiche risolte, la tipologia di +soluzione, le persone che lavorano alla patch, ogni effetto rilevante +sulle prestazioni e tutto ciò che può servire per la comprensione della +patch. Assicuratevi che il changelog dica *perché*, vale la pena aggiungere +la patch; un numero sorprendente di sviluppatori sbaglia nel fornire tale +informazione. + +Qualsiasi codice che aggiunge una nuova interfaccia in spazio utente - inclusi +nuovi file in sysfs o /proc - dovrebbe includere la documentazione di tale +interfaccia così da permette agli sviluppatori dello spazio utente di sapere +con cosa stanno lavorando. Consultate: Documentation/ABI/README per avere una +descrizione di come questi documenti devono essere impostati e quali +informazioni devono essere fornite. + +Il file :ref:`Documentation/translations/it_IT/admin-guide/kernel-parameters.rst ` +descrive tutti i parametri di avvio del kernel. Ogni patch che aggiunga +nuovi parametri dovrebbe aggiungere nuove voci a questo file. + +Ogni nuova configurazione deve essere accompagnata da un testo di supporto +che spieghi chiaramente le opzioni e spieghi quando l'utente potrebbe volerle +selezionare. + +Per molti sottosistemi le informazioni sull'API interna sono documentate sotto +forma di commenti formattati in maniera particolare; questi commenti possono +essere estratti e formattati in differenti modi attraverso lo script +"kernel-doc". Se state lavorando all'interno di un sottosistema che ha +commenti kerneldoc dovreste mantenerli e aggiungerli, in maniera appropriata, +per le funzioni disponibili esternamente. Anche in aree che non sono molto +documentate, non c'è motivo per non aggiungere commenti kerneldoc per il +futuro; infatti, questa può essere un'attività utile per sviluppatori novizi +del kernel. Il formato di questi commenti, assieme alle informazione su come +creare modelli per kerneldoc, possono essere trovati in +:ref:`Documentation/translations/it_IT/doc-guide/ `. + +Chiunque legga un ammontare significativo di codice kernel noterà che, spesso, +i commenti si fanno maggiormente notare per la loro assenza. Ancora una volta, +le aspettative verso il nuovo codice sono più alte rispetto al passato; +inserire codice privo di commenti sarà più difficile. Detto ciò, va aggiunto +che non si desiderano commenti prolissi per il codice. Il codice dovrebbe +essere, di per sé, leggibile, con dei commenti che spieghino gli aspetti più +sottili. + +Determinate cose dovrebbero essere sempre commentate. L'uso di barriere +di memoria dovrebbero essere accompagnate da una riga che spieghi perché sia +necessaria. Le regole di sincronizzazione per le strutture dati, generalmente, +necessitano di una spiegazioni da qualche parte. Le strutture dati più +importanti, in generale, hanno bisogno di una documentazione onnicomprensiva. +Le dipendenze che non sono ovvie tra bit separati di codice dovrebbero essere +indicate. Tutto ciò che potrebbe indurre un inserviente del codice a fare +una "pulizia" incorretta, ha bisogno di un commento che dica perché è stato +fatto in quel modo. E così via. + +Cambiamenti interni dell'API +---------------------------- + +L'interfaccia binaria fornita dal kernel allo spazio utente non può essere +rotta tranne che in circostanze eccezionali. L'interfaccia di programmazione +interna al kernel, invece, è estremamente fluida e può essere modificata al +bisogno. Se vi trovate a dover lavorare attorno ad un'API del kernel o +semplicemente non state utilizzando una funzionalità offerta perché questa +non rispecchia i vostri bisogni, allora questo potrebbe essere un segno che +l'API ha bisogno di essere cambiata. In qualità di sviluppatore del kernel, +hai il potere di fare questo tipo di modifica. + +Ci sono ovviamente alcuni punti da cogliere. I cambiamenti API possono essere +fatti, ma devono essere giustificati. Quindi ogni patch che porta ad una +modifica dell'API interna dovrebbe essere accompagnata da una descrizione +della modifica in sé e del perché essa è necessaria. Questo tipo di +cambiamenti dovrebbero, inoltre, essere fatti in una patch separata, invece di +essere sepolti all'interno di una patch più grande. + +L'altro punto da cogliere consiste nel fatto che uno sviluppatore che +modifica l'API deve, in generale, essere responsabile della correzione +di tutto il codice del kernel che viene rotto per via della sua modifica. +Per una funzione ampiamente usata, questo compito può condurre letteralmente +a centinaia o migliaia di modifiche, molte delle quali sono in conflitto con +il lavoro svolto da altri sviluppatori. Non c'è bisogno di dire che questo +può essere un lavoro molto grosso, quindi è meglio essere sicuri che la +motivazione sia ben solida. Notate che lo strumento Coccinelle può fornire +un aiuto con modifiche estese dell'API. + +Quando viene fatta una modifica API incompatibile, una persona dovrebbe, +quando possibile, assicurarsi che quel codice non aggiornato sia trovato +dal compilatore. Questo vi aiuterà ad essere sicuri d'avere trovato, +tutti gli usi di quell'interfaccia. Inoltre questo avviserà gli sviluppatori +di codice fuori dal kernel che c'è un cambiamento per il quale è necessario del +lavoro. Il supporto al codice fuori dal kernel non è qualcosa di cui gli +sviluppatori del kernel devono preoccuparsi, ma non dobbiamo nemmeno rendere +più difficile del necessario la vita agli sviluppatori di questo codice. diff --git a/Documentation/translations/it_IT/process/5.Posting.rst b/Documentation/translations/it_IT/process/5.Posting.rst new file mode 100644 index 000000000..cf92a16ed --- /dev/null +++ b/Documentation/translations/it_IT/process/5.Posting.rst @@ -0,0 +1,364 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/5.Posting.rst ` +:Translator: Federico Vaga + +.. _it_development_posting: + +Pubblicare modifiche +==================== + +Prima o poi arriva il momento in cui il vostro lavoro è pronto per essere +presentato alla comunità per una revisione ed eventualmente per la sua +inclusione nel ramo principale del kernel. Com'era prevedibile, +la comunità di sviluppo del kernel ha elaborato un insieme di convenzioni +e di procedure per la pubblicazione delle patch; seguirle renderà la vita +più facile a tutti quanti. Questo documento cercherà di coprire questi +argomenti con un ragionevole livello di dettaglio; più informazioni possono +essere trovare nella cartella 'Documentation', nei file +:ref:`translations/it_IT/process/submitting-patches.rst ` +e :ref:`translations/it_IT/process/submit-checklist.rst `. + + +Quando pubblicarle +------------------ + +C'è sempre una certa resistenza nel pubblicare patch finché non sono +veramente "pronte". Per semplici patch questo non è un problema. +Ma quando il lavoro è di una certa complessità, c'è molto da guadagnare +dai riscontri che la comunità può darvi prima che completiate il lavoro. +Dovreste considerare l'idea di pubblicare un lavoro incompleto, o anche +preparare un ramo git disponibile agli sviluppatori interessati, cosicché +possano stare al passo col vostro lavoro in qualunque momento. + +Quando pubblicate del codice che non è considerato pronto per l'inclusione, +è bene che lo diciate al momento della pubblicazione. Inoltre, aggiungete +informazioni sulle cose ancora da sviluppare e sui problemi conosciuti. +Poche persone guarderanno delle patch che si sa essere fatte a metà, +ma quelli che lo faranno penseranno di potervi aiutare a condurre il vostro +sviluppo nella giusta direzione. + + +Prima di creare patch +--------------------- + +Ci sono un certo numero di cose che dovreste fare prima di considerare +l'invio delle patch alla comunità di sviluppo. Queste cose includono: + + - Verificare il codice fino al massimo che vi è consentito. Usate gli + strumenti di debug del kernel, assicuratevi che il kernel compili con + tutte le più ragionevoli combinazioni d'opzioni, usate cross-compilatori + per compilare il codice per differenti architetture, eccetera. + + - Assicuratevi che il vostro codice sia conforme alla linee guida del + kernel sullo stile del codice. + + - La vostra patch ha delle conseguenze in termini di prestazioni? + Se è così, dovreste eseguire dei *benchmark* che mostrino il loro + impatto (anche positivo); un riassunto dei risultati dovrebbe essere + incluso nella patch. + + - Siate certi d'avere i diritti per pubblicare il codice. Se questo + lavoro è stato fatto per un datore di lavoro, egli avrà dei diritti su + questo lavoro e dovrà quindi essere d'accordo alla sua pubblicazione + con una licenza GPL + +Come regola generale, pensarci un po' di più prima di inviare il codice +ripaga quasi sempre lo sforzo. + + +Preparazione di una patch +------------------------- + +La preparazione delle patch per la pubblicazione può richiedere una quantità +di lavoro significativa, ma, ripetiamolo ancora, generalmente sconsigliamo +di risparmiare tempo in questa fase, anche sul breve periodo. + +Le patch devono essere preparate per una specifica versione del kernel. +Come regola generale, una patch dovrebbe basarsi sul ramo principale attuale +così come lo si trova nei sorgenti git di Linus. Quando vi basate sul ramo +principale, cominciate da un punto di rilascio ben noto - uno stabile o +un -rc - piuttosto che creare il vostro ramo da quello principale in un punto +a caso. + +Per facilitare una revisione e una verifica più estesa, potrebbe diventare +necessaria la produzione di versioni per -mm, linux-next o i sorgenti di un +sottosistema. Basare questa patch sui suddetti sorgenti potrebbe richiedere +un lavoro significativo nella risoluzione dei conflitti e nella correzione dei +cambiamenti di API; questo potrebbe variare a seconda dell'area d'interesse +della vostra patch e da quello che succede altrove nel kernel. + +Solo le modifiche più semplici dovrebbero essere preparate come una singola +patch; tutto il resto dovrebbe essere preparato come una serie logica di +modifiche. Spezzettare le patch è un po' un'arte; alcuni sviluppatori +passano molto tempo nel capire come farlo in modo che piaccia alla comunità. +Ci sono alcune regole spannometriche, che comunque possono aiutare +considerevolmente: + + - La serie di patch che pubblicherete, quasi sicuramente, non sarà + come quella che trovate nel vostro sistema di controllo di versione. + Invece, le vostre modifiche dovranno essere considerate nella loro forma + finale, e quindi separate in parti che abbiano un senso. Gli sviluppatori + sono interessati in modifiche che siano discrete e indipendenti, non + alla strada che avete percorso per ottenerle. + + - Ogni modifica logicamente indipendente dovrebbe essere preparata come una + patch separata. Queste modifiche possono essere piccole ("aggiunto un + campo in questa struttura") o grandi (l'aggiunta di un driver nuovo, + per esempio), ma dovrebbero essere concettualmente piccole da permettere + una descrizione in una sola riga. Ogni patch dovrebbe fare modifiche + specifiche che si possano revisionare indipendentemente e di cui si possa + verificare la veridicità. + + - Giusto per riaffermare quando detto sopra: non mischiate diversi tipi di + modifiche nella stessa patch. Se una modifica corregge un baco critico + per la sicurezza, riorganizza alcune strutture, e riformatta il codice, + ci sono buone probabilità che venga ignorata e che la correzione importante + venga persa. + + - Ogni modifica dovrebbe portare ad un kernel che compila e funziona + correttamente; se la vostra serie di patch si interrompe a metà il + risultato dovrebbe essere comunque un kernel funzionante. L'applicazione + parziale di una serie di patch è uno scenario comune nel quale il + comando "git bisect" viene usato per trovare delle regressioni; se il + risultato è un kernel guasto, renderete la vita degli sviluppatori più + difficile così come quella di chi s'impegna nel nobile lavoro di + scovare i problemi. + + - Però, non strafate. Una volta uno sviluppatore pubblicò una serie di 500 + patch che modificavano un unico file - un atto che non lo rese la persona + più popolare sulla lista di discussione del kernel. Una singola patch + può essere ragionevolmente grande fintanto che contenga un singolo + cambiamento *logico*. + + - Potrebbe essere allettante l'idea di aggiungere una nuova infrastruttura + come una serie di patch, ma di lasciare questa infrastruttura inutilizzata + finché l'ultima patch della serie non abilita tutto quanto. Quando è + possibile, questo dovrebbe essere evitato; se questa serie aggiunge delle + regressioni, "bisect" indicherà quest'ultima patch come causa del + problema anche se il baco si trova altrove. Possibilmente, quando una + patch aggiunge del nuovo codice dovrebbe renderlo attivo immediatamente. + +Lavorare per creare la serie di patch perfetta potrebbe essere frustrante +perché richiede un certo tempo e soprattutto dopo che il "vero lavoro" è +già stato fatto. Quando ben fatto, comunque, è tempo ben speso. + + +Formattazione delle patch e i changelog +--------------------------------------- + +Quindi adesso avete una serie perfetta di patch pronte per la pubblicazione, +ma il lavoro non è davvero finito. Ogni patch deve essere preparata con +un messaggio che spieghi al resto del mondo, in modo chiaro e veloce, +il suo scopo. Per ottenerlo, ogni patch sarà composta dai seguenti elementi: + + - Un campo opzionale "From" col nome dell'autore della patch. Questa riga + è necessaria solo se state passando la patch di qualcun altro via email, + ma nel dubbio non fa di certo male aggiungerlo. + + - Una descrizione di una riga che spieghi cosa fa la patch. Questo + messaggio dovrebbe essere sufficiente per far comprendere al lettore lo + scopo della patch senza altre informazioni. Questo messaggio, + solitamente, presenta in testa il nome del sottosistema a cui si riferisce, + seguito dallo scopo della patch. Per esempio: + + :: + + gpio: fix build on CONFIG_GPIO_SYSFS=n + + - Una riga bianca seguita da una descrizione dettagliata della patch. + Questa descrizione può essere lunga tanto quanto serve; dovrebbe spiegare + cosa fa e perché dovrebbe essere aggiunta al kernel. + + - Una o più righe etichette, con, minimo, una riga *Signed-off-by:* + col nome dall'autore della patch. Queste etichette verranno descritte + meglio più avanti. + +Gli elementi qui sopra, assieme, formano il changelog di una patch. +Scrivere un buon changelog è cruciale ma è spesso un'arte trascurata; +vale la pena spendere qualche parola in più al riguardo. Quando scrivete +un changelog dovreste tenere ben presente che molte persone leggeranno +le vostre parole. Queste includono i manutentori di un sotto-sistema, e i +revisori che devono decidere se la patch debba essere inclusa o no, +le distribuzioni e altri manutentori che cercano di valutare se la patch +debba essere applicata su kernel più vecchi, i cacciatori di bachi che si +chiederanno se la patch è la causa di un problema che stanno cercando, +gli utenti che vogliono sapere com'è cambiato il kernel, e molti altri. +Un buon changelog fornisce le informazioni necessarie a tutte queste +persone nel modo più diretto e conciso possibile. + +A questo scopo, la riga riassuntiva dovrebbe descrivere gli effetti della +modifica e la motivazione della patch nel modo migliore possibile nonostante +il limite di una sola riga. La descrizione dettagliata può spiegare meglio +i temi e fornire maggiori informazioni. Se una patch corregge un baco, +citate, se possibile, il commit che lo introdusse (e per favore, quando +citate un commit aggiungete sia il suo identificativo che il titolo), +Se il problema è associabile ad un file di log o all' output del compilatore, +includeteli al fine d'aiutare gli altri a trovare soluzioni per lo stesso +problema. Se la modifica ha lo scopo di essere di supporto a sviluppi +successivi, ditelo. Se le API interne vengono cambiate, dettagliate queste +modifiche e come gli altri dovrebbero agire per applicarle. In generale, +più riuscirete ad entrare nei panni di tutti quelli che leggeranno il +vostro changelog, meglio sarà il changelog (e il kernel nel suo insieme). + +Non serve dirlo, un changelog dovrebbe essere il testo usato nel messaggio +di commit in un sistema di controllo di versione. Sarà seguito da: + + - La patch stessa, nel formato unificato per patch ("-u"). Usare + l'opzione "-p" assocerà alla modifica il nome della funzione alla quale + si riferisce, rendendo il risultato più facile da leggere per gli altri. + +Dovreste evitare di includere nelle patch delle modifiche per file +irrilevanti (quelli generati dal processo di generazione, per esempio, o i file +di backup del vostro editor). Il file "dontdiff" nella cartella Documentation +potrà esservi d'aiuto su questo punto; passatelo a diff con l'opzione "-X". + +Le etichette sopracitate danno un'idea di come una patch prende vita e sono +descritte nel dettaglio nel documento +:ref:`Documentation/translations/it_IT/process/submitting-patches.rst `. +Qui di seguito un breve riassunto. + +Un'etichetta ci può dire quale commit ha introdotto il problema che viene corretto nella patch:: + + Fixes: 1f2e3d4c5b6a ("The first line of the commit specified by the first 12 characters of its SHA-1 ID") + +Un'altra etichetta viene usata per fornire collegamenti a pagine web contenenti +maggiori informazioni, per esempio un rapporto circa il baco risolto dalla +patch, oppure un documento con le specifiche implementate dalla patch:: + + Link: https://example.com/somewhere.html optional-other-stuff + +Alcuni manutentori aggiungono quest'etichetta alla patch per fare riferimento +alla più recente discussione pubblica. A volte questo è fatto automaticamente da +alcuni strumenti come b4 or un *hook* git come quello descritto qui +'Documentation/translations/it_IT/maintainer/configure-git.rst' + +Un terzo tipo di etichetta viene usato per indicare chi ha contribuito allo +sviluppo della patch. Tutte queste etichette seguono il formato:: + + tag: Full Name optional-other-stuff + +Le etichette in uso più comuni sono: + + - Signed-off-by: questa è la certificazione che lo sviluppatore ha il diritto + di sottomettere la patch per l'integrazione nel kernel. Questo rappresenta + il consenso verso il certificato d'origine degli sviluppatori, il testo + completo potrà essere trovato in + :ref:`Documentation/translations/it_IT/process/submitting-patches.rst `. + Codice che non presenta una firma appropriata non potrà essere integrato. + + - Co-developed-by: indica che la patch è stata cosviluppata da diversi + sviluppatori; viene usato per assegnare più autori (in aggiunta a quello + associato all'etichetta From:) quando più persone lavorano ad una patch. + Ogni Co-developed-by: dev'essere seguito immediatamente da un Signed-off-by: + del corrispondente coautore. Maggiori dettagli ed esempi sono disponibili + in :ref:`Documentation/translations/it_IT/process/submitting-patches.rst `. + + - Acked-by: indica il consenso di un altro sviluppatore (spesso il manutentore + del codice in oggetto) all'integrazione della patch nel kernel. + + - Tested-by: menziona la persona che ha verificato la patch e l'ha trovata + funzionante. + + - Reviwed-by: menziona lo sviluppatore che ha revisionato la patch; per + maggiori dettagli leggete la dichiarazione dei revisori in + :ref:`Documentation/translations/it_IT/process/submitting-patches.rst ` + + - Reported-by: menziona l'utente che ha riportato il problema corretto da + questa patch; quest'etichetta viene usata per dare credito alle persone + che hanno verificato il codice e ci hanno fatto sapere quando le cose non + funzionavano correttamente. + + - Cc: la persona menzionata ha ricevuto una copia della patch ed ha avuto + l'opportunità di commentarla. + +State attenti ad aggiungere queste etichette alla vostra patch: solo +"Cc:" può essere aggiunta senza il permesso esplicito della persona menzionata. + +Inviare la modifica +------------------- + +Prima di inviare la vostra patch, ci sarebbero ancora un paio di cose di cui +dovreste aver cura: + + - Siete sicuri che il vostro programma di posta non corromperà le patch? + Le patch che hanno spazi bianchi in libertà o andate a capo aggiunti + dai programmi di posta non funzioneranno per chi le riceve, e spesso + non verranno nemmeno esaminate in dettaglio. Se avete un qualsiasi dubbio, + inviate la patch a voi stessi e verificate che sia integra. + + :ref:`Documentation/translations/it_IT/process/email-clients.rst ` + contiene alcuni suggerimenti utili sulla configurazione dei programmi + di posta al fine di inviare patch. + + - Siete sicuri che la vostra patch non contenga sciocchi errori? Dovreste + sempre processare le patch con scripts/checkpatch.pl e correggere eventuali + problemi riportati. Per favore tenete ben presente che checkpatch.pl non è + più intelligente di voi, nonostante sia il risultato di un certa quantità di + ragionamenti su come debba essere una patch per il kernel. Se seguire + i suggerimenti di checkpatch.pl rende il codice peggiore, allora non fatelo. + +Le patch dovrebbero essere sempre inviate come testo puro. Per favore non +inviatele come allegati; questo rende molto più difficile, per i revisori, +citare parti della patch che si vogliono commentare. Invece, mettete la vostra +patch direttamente nel messaggio. + +Quando inviate le patch, è importante inviarne una copia a tutte le persone che +potrebbero esserne interessate. Al contrario di altri progetti, il kernel +incoraggia le persone a peccare nell'invio di tante copie; non presumente che +le persone interessate vedano i vostri messaggi sulla lista di discussione. +In particolare le copie dovrebbero essere inviate a: + + - I manutentori dei sottosistemi affetti della modifica. Come descritto + in precedenza, il file MAINTAINERS è il primo luogo dove cercare i nomi + di queste persone. + + - Altri sviluppatori che hanno lavorato nello stesso ambiente - specialmente + quelli che potrebbero lavorarci proprio ora. Usate git potrebbe essere + utile per vedere chi altri ha modificato i file su cui state lavorando. + + - Se state rispondendo a un rapporto su un baco, o a una richiesta di + funzionalità, includete anche gli autori di quei rapporti/richieste. + + - Inviate una copia alle liste di discussione interessate, o, se nient'altro + è adatto, alla lista linux-kernel + + - Se state correggendo un baco, pensate se la patch dovrebbe essere inclusa + nel prossimo rilascio stabile. Se è così, la lista di discussione + stable@vger.kernel.org dovrebbe riceverne una copia. Aggiungete anche + l'etichetta "Cc: stable@vger.kernel.org" nella patch stessa; questo + permetterà alla squadra *stable* di ricevere una notifica quando questa + correzione viene integrata nel ramo principale. + +Quando scegliete i destinatari della patch, è bene avere un'idea di chi +pensiate che sia colui che, eventualmente, accetterà la vostra patch e +la integrerà. Nonostante sia possibile inviare patch direttamente a +Linus Torvalds, e lasciare che sia lui ad integrarle,solitamente non è la +strada migliore da seguire. Linus è occupato, e ci sono dei manutentori di +sotto-sistema che controllano una parte specifica del kernel. Solitamente, +vorreste che siano questi manutentori ad integrare le vostre patch. Se non +c'è un chiaro manutentore, l'ultima spiaggia è spesso Andrew Morton. + +Le patch devono avere anche un buon oggetto. Il tipico formato per l'oggetto +di una patch assomiglia a questo: + +:: + + [PATCH nn/mm] subsys: one-line description of the patch + +dove "nn" è il numero ordinale della patch, "mm" è il numero totale delle patch +nella serie, e "subsys" è il nome del sottosistema interessato. Chiaramente, +nn/mm può essere omesso per una serie composta da una singola patch. + +Se avete una significative serie di patch, è prassi inviare una descrizione +introduttiva come parte zero. Tuttavia questa convenzione non è universalmente +seguita; se la usate, ricordate che le informazioni nell'introduzione non +faranno parte del changelog del kernel. Quindi per favore, assicuratevi che +ogni patch abbia un changelog completo. + +In generale, la seconda parte e quelle successive di una patch "composta" +dovrebbero essere inviate come risposta alla prima, cosicché vengano viste +come un unico *thread*. Strumenti come git e quilt hanno comandi per inviare +gruppi di patch con la struttura appropriata. Se avete una serie lunga +e state usando git, per favore state alla larga dall'opzione --chain-reply-to +per evitare di creare un annidamento eccessivo. diff --git a/Documentation/translations/it_IT/process/6.Followthrough.rst b/Documentation/translations/it_IT/process/6.Followthrough.rst new file mode 100644 index 000000000..df7d5fb28 --- /dev/null +++ b/Documentation/translations/it_IT/process/6.Followthrough.rst @@ -0,0 +1,240 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/6.Followthrough.rst ` +:Translator: Alessia Mantegazza + +.. _it_development_followthrough: + +============= +Completamento +============= + +A questo punto, avete seguito le linee guida fino a questo punto e, con +l'aggiunta delle vostre capacità ingegneristiche, avete pubblicato una serie +perfetta di patch. Uno dei più grandi errori che possono essere commessi +persino da sviluppatori kernel esperti è quello di concludere che il +lavoro sia ormai finito. In verità, la pubblicazione delle patch +simboleggia una transizione alla fase successiva del processo, con, +probabilmente, ancora un po' di lavoro da fare. + +È raro che una modifica sia così bella alla sua prima pubblicazione che non +ci sia alcuno spazio di miglioramento. Il programma di sviluppo del kernel +riconosce questo fatto e quindi, è fortemente orientato al miglioramento +del codice pubblicato. Voi, in qualità di autori del codice, dovrete +lavorare con la comunità del kernel per assicurare che il vostro codice +mantenga gli standard qualitativi richiesti. Un fallimento in questo +processo è quasi come impedire l'inclusione delle vostre patch nel +ramo principale. + +Lavorare con i revisori +======================= + +Una patch che abbia una certa rilevanza avrà ricevuto numerosi commenti +da parte di altri sviluppatori dato che avranno revisionato il codice. +Lavorare con i revisori può rivelarsi, per molti sviluppatori, la parte +più intimidatoria del processo di sviluppo del kernel. La vita può esservi +resa molto più facile se tenete presente alcuni dettagli: + + - Se avete descritto la vostra modifica correttamente, i revisori ne + comprenderanno il valore e il perché vi siete presi il disturbo di + scriverla. Ma tale valore non li tratterrà dal porvi una domanda + fondamentale: come verrà mantenuto questo codice nel kernel nei prossimi + cinque o dieci anni? Molti dei cambiamenti che potrebbero esservi + richiesti - da piccoli problemi di stile a sostanziali ristesure - + vengono dalla consapevolezza che Linux resterà in circolazione e in + continuo sviluppo ancora per diverse decadi. + + - La revisione del codice è un duro lavoro, ed è un mestiere poco + riconosciuto; le persone ricordano chi ha scritto il codice, ma meno + fama è attribuita a chi lo ha revisionato. Quindi i revisori potrebbero + divenire burberi, specialmente quando vendono i medesimi errori venire + fatti ancora e ancora. Se ricevete una revisione che vi sembra abbia + un tono arrabbiato, insultante o addirittura offensivo, resistente alla + tentazione di rispondere a tono. La revisione riguarda il codice e non + la persona, e i revisori non vi stanno attaccando personalmente. + + - Similarmente, i revisori del codice non stanno cercando di promuovere + i loro interessi a vostre spese. Gli sviluppatori del kernel spesso si + aspettano di lavorare sul kernel per anni, ma sanno che il loro datore + di lavoro può cambiare. Davvero, senza praticamente eccezioni, loro + stanno lavorando per la creazione del miglior kernel possibile; non + stanno cercando di creare un disagio ad aziende concorrenti. + +Quello che si sta cercando di dire è che, quando i revisori vi inviano degli +appunti dovete fare attenzione alle osservazioni tecniche che vi stanno +facendo. Non lasciate che il loro modo di esprimersi o il vostro orgoglio +impediscano che ciò accada. Quando avete dei suggerimenti sulla revisione, +prendetevi il tempo per comprendere cosa il revisore stia cercando di +comunicarvi. Se possibile, sistemate le cose che il revisore vi chiede di +modificare. E rispondete al revisore ringraziandolo e spiegando come +intendete fare. + +Notate che non dovete per forza essere d'accordo con ogni singola modifica +suggerita dai revisori. Se credete che il revisore non abbia compreso +il vostro codice, spiegateglielo. Se avete un'obiezione tecnica da fargli +su di una modifica suggerita, spiegatela inserendo anche la vostra soluzione +al problema. Se la vostra spiegazione ha senso, il revisore la accetterà. +Tuttavia, la vostra motivazione potrebbe non essere del tutto persuasiva, +specialmente se altri iniziano ad essere d'accordo con il revisore. +Prendetevi quindi un po' di tempo per pensare ancora alla cosa. Può risultare +facile essere accecati dalla propria soluzione al punto che non realizzate che +c'è qualcosa di fondamentalmente sbagliato o, magari, non state nemmeno +risolvendo il problema giusto. + +Andrew Morton suggerisce che ogni suggerimento di revisione che non è +presente nella modifica del codice dovrebbe essere inserito in un commento +aggiuntivo; ciò può essere d'aiuto ai futuri revisori nell'evitare domande +che sorgono al primo sguardo. + +Un errore fatale è quello di ignorare i commenti di revisione nella speranza +che se ne andranno. Non andranno via. Se pubblicherete nuovamente il +codice senza aver risposto ai commenti ricevuti, probabilmente le vostre +modifiche non andranno da nessuna parte. + +Parlando di ripubblicazione del codice: per favore tenete a mente che i +revisori non ricorderanno tutti i dettagli del codice che avete pubblicato +l'ultima volta. Quindi è sempre una buona idea quella di ricordare ai +revisori le questioni sollevate precedetemene e come le avete risolte. +I revisori non dovrebbero star lì a cercare all'interno degli archivi per +famigliarizzare con ciò che è stato detto l'ultima volta; se li aiutate +in questo senso, saranno di umore migliore quando riguarderanno il vostro +codice. + +Se invece avete cercato di far tutto correttamente ma le cose continuano +a non andar bene? Molti disaccordi di natura tecnica possono essere risolti +attraverso la discussione, ma ci sono volte dove qualcuno deve prendere +una decisione. Se credete veramente che tale decisione andrà contro di voi +ingiustamente, potete sempre tentare di rivolgervi a qualcuno più +in alto di voi. Per cose di questo genere la persona con più potere è +Andrew Morton. Andrew è una figura molto rispettata all'interno della +comunità di sviluppo del kernel; lui può spesso sbrogliare situazioni che +sembrano irrimediabilmente bloccate. Rivolgersi ad Andrew non deve essere +fatto alla leggera, e non deve essere fatto prima di aver esplorato tutte +le altre alternative. E tenete a mente, ovviamente, che nemmeno lui +potrebbe non essere d'accordo con voi. + +Cosa accade poi +=============== + +Se la modifica è ritenuta un elemento valido da essere aggiunta al kernel, +e una volta che la maggior parte degli appunti dei revisori sono stati +sistemati, il passo successivo solitamente è quello di entrare in un +sottosistema gestito da un manutentore. Come ciò avviene dipende dal +sottosistema medesimo; ogni manutentore ha il proprio modo di fare le cose. +In particolare, ci potrebbero essere diversi sorgenti - uno, magari, dedicato +alle modifiche pianificate per la finestra di fusione successiva, e un altro +per il lavoro di lungo periodo. + +Per le modifiche proposte in aree per le quali non esiste un sottosistema +preciso (modifiche di gestione della memoria, per esempio), i sorgenti di +ripiego finiscono per essere -mm. Ed anche le modifiche che riguardano +più sottosistemi possono finire in quest'ultimo. + +L'inclusione nei sorgenti di un sottosistema può comportare per una patch, +un alto livello di visibilità. Ora altri sviluppatori che stanno lavorando +in quei medesimi sorgenti avranno le vostre modifiche. I sottosistemi +solitamente riforniscono anche Linux-next, rendendo i propri contenuti +visibili all'intera comunità di sviluppo. A questo punto, ci sono buone +possibilità per voi di ricevere ulteriori commenti da un nuovo gruppo di +revisori; anche a questi commenti dovrete rispondere come avete già fatto per +gli altri. + +Ciò che potrebbe accadere a questo punto, in base alla natura della vostra +modifica, riguarda eventuali conflitti con il lavoro svolto da altri. +Nella peggiore delle situazioni, i conflitti più pesanti tra modifiche possono +concludersi con la messa a lato di alcuni dei lavori svolti cosicché le +modifiche restanti possano funzionare ed essere integrate. Altre volte, la +risoluzione dei conflitti richiederà del lavoro con altri sviluppatori e, +possibilmente, lo spostamento di alcune patch da dei sorgenti a degli altri +in modo da assicurare che tutto sia applicato in modo pulito. Questo lavoro +può rivelarsi una spina nel fianco, ma consideratevi fortunati: prima +dell'avvento dei sorgenti linux-next, questi conflitti spesso emergevano solo +durante l'apertura della finestra di integrazione e dovevano essere smaltiti +in fretta. Ora essi possono essere risolti comodamente, prima dell'apertura +della finestra. + +Un giorno, se tutto va bene, vi collegherete e vedrete che la vostra patch +è stata inserita nel ramo principale de kernel. Congratulazioni! Terminati +i festeggiamenti (nel frattempo avrete inserito il vostro nome nel file +MAINTAINERS) vale la pena ricordare una piccola cosa, ma importante: il +lavoro non è ancora finito. L'inserimento nel ramo principale porta con se +nuove sfide. + +Cominciamo con il dire che ora la visibilità della vostra modifica è +ulteriormente cresciuta. Ci potrebbe portare ad una nuova fase di +commenti dagli sviluppatori che non erano ancora a conoscenza della vostra +patch. Ignorarli potrebbe essere allettante dato che non ci sono più +dubbi sull'integrazione della modifica. Resistete a tale tentazione, dovete +mantenervi disponibili agli sviluppatori che hanno domande o suggerimenti +per voi. + +Ancora più importante: l'inclusione nel ramo principale mette il vostro +codice nelle mani di un gruppo di *tester* molto più esteso. Anche se avete +contribuito ad un driver per un hardware che non è ancora disponibile, sarete +sorpresi da quante persone inseriranno il vostro codice nei loro kernel. +E, ovviamente, dove ci sono *tester*, ci saranno anche dei rapporti su +eventuali bachi. + +La peggior specie di rapporti sono quelli che indicano delle regressioni. +Se la vostra modifica causa una regressione, avrete un gran numero di +occhi puntati su di voi; la regressione deve essere sistemata il prima +possibile. Se non vorrete o non sarete capaci di sistemarla (e nessuno +lo farà per voi), la vostra modifica sarà quasi certamente rimossa durante +la fase di stabilizzazione. Oltre alla perdita di tutto il lavoro svolto +per far si che la vostra modifica fosse inserita nel ramo principale, +l'avere una modifica rimossa a causa del fallimento nel sistemare una +regressione, potrebbe rendere più difficile per voi far accettare +il vostro lavoro in futuro. + +Dopo che ogni regressione è stata affrontata, ci potrebbero essere altri +bachi ordinari da "sconfiggere". Il periodo di stabilizzazione è la +vostra migliore opportunità per sistemare questi bachi e assicurarvi che +il debutto del vostro codice nel ramo principale del kernel sia il più solido +possibile. Quindi, per favore, rispondete ai rapporti sui bachi e ponete +rimedio, se possibile, a tutti i problemi. È a questo che serve il periodo +di stabilizzazione; potete iniziare creando nuove fantastiche modifiche +una volta che ogni problema con le vecchie sia stato risolto. + +Non dimenticate che esistono altre pietre miliari che possono generare +rapporti sui bachi: il successivo rilascio stabile, quando una distribuzione +importante usa una versione del kernel nel quale è presente la vostra +modifica, eccetera. Il continuare a rispondere a questi rapporti è fonte di +orgoglio per il vostro lavoro. Se questa non è una sufficiente motivazione, +allora, è anche consigliabile considera che la comunità di sviluppo ricorda +gli sviluppatori che hanno perso interesse per il loro codice una volta +integrato. La prossima volta che pubblicherete una patch, la comunità +la valuterà anche sulla base del fatto che non sarete disponibili a +prendervene cura anche nel futuro. + + +Altre cose che posso accadere +============================= + +Un giorno, potreste aprire la vostra email e vedere che qualcuno vi ha +inviato una patch per il vostro codice. Questo, dopo tutto, è uno dei +vantaggi di avere il vostro codice "là fuori". Se siete d'accordo con +la modifica, potrete anche inoltrarla ad un manutentore di sottosistema +(assicuratevi di includere la riga "From:" cosicché l'attribuzione sia +corretta, e aggiungete una vostra firma "Signed-off-by"), oppure inviate +un "Acked-by:" e lasciate che l'autore originale la invii. + +Se non siete d'accordo con la patch, inviate una risposta educata +spiegando il perché. Se possibile, dite all'autore quali cambiamenti +servirebbero per rendere la patch accettabile da voi. C'è una certa +riluttanza nell'inserire modifiche con un conflitto fra autore +e manutentore del codice, ma solo fino ad un certo punto. Se siete visti +come qualcuno che blocca un buon lavoro senza motivo, quelle patch vi +passeranno oltre e andranno nel ramo principale in ogni caso. Nel kernel +Linux, nessuno ha potere di veto assoluto su alcun codice. Eccezione +fatta per Linus, forse. + +In rarissime occasioni, potreste vedere qualcosa di completamente diverso: +un altro sviluppatore che pubblica una soluzione differente al vostro +problema. A questo punto, c'è una buona probabilità che una delle due +modifiche non verrà integrata, e il "c'ero prima io" non è considerato +un argomento tecnico rilevante. Se la modifica di qualcun'altro rimpiazza +la vostra ed entra nel ramo principale, esiste un unico modo di reagire: +siate contenti che il vostro problema sia stato risolto e andate avanti con +il vostro lavoro. L'avere un vostro lavoro spintonato da parte in questo +modo può essere avvilente e scoraggiante, ma la comunità ricorderà come +avrete reagito anche dopo che avrà dimenticato quale fu la modifica accettata. diff --git a/Documentation/translations/it_IT/process/7.AdvancedTopics.rst b/Documentation/translations/it_IT/process/7.AdvancedTopics.rst new file mode 100644 index 000000000..cc1cff5d2 --- /dev/null +++ b/Documentation/translations/it_IT/process/7.AdvancedTopics.rst @@ -0,0 +1,191 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/7.AdvancedTopics.rst ` +:Translator: Federico Vaga + +.. _it_development_advancedtopics: + +Argomenti avanzati +================== + +A questo punto, si spera, dovreste avere un'idea su come funziona il processo +di sviluppo. Ma rimane comunque molto da imparare! Questo capitolo copre +alcuni argomenti che potrebbero essere utili per gli sviluppatori che stanno +per diventare parte integrante del processo di sviluppo del kernel. + +Gestire le modifiche con git +----------------------------- + +L'uso di un sistema distribuito per il controllo delle versioni del kernel +ebbe iniziò nel 2002 quando Linux iniziò a provare il programma proprietario +BitKeeper. Nonostante l'uso di BitKeeper fosse opinabile, di certo il suo +approccio alla gestione dei sorgenti non lo era. Un sistema distribuito per +il controllo delle versioni accelerò immediatamente lo sviluppo del kernel. +Oggigiorno, ci sono diverse alternative libere a BitKeeper. Per il meglio o il +peggio, il progetto del kernel ha deciso di usare git per gestire i sorgenti. + +Gestire le modifiche con git può rendere la vita dello sviluppatore molto +più facile, specialmente quando il volume delle modifiche cresce. +Git ha anche i suoi lati taglienti che possono essere pericolosi; è uno +strumento giovane e potente che è ancora in fase di civilizzazione da parte +dei suoi sviluppatori. Questo documento non ha lo scopo di insegnare l'uso +di git ai suoi lettori; ci sarebbe materiale a sufficienza per un lungo +documento al riguardo. Invece, qui ci concentriamo in particolare su come +git è parte del processo di sviluppo del kernel. Gli sviluppatori che +desiderassero diventare agili con git troveranno più informazioni ai +seguenti indirizzi: + + http://git-scm.com/ + + http://www.kernel.org/pub/software/scm/git/docs/user-manual.html + +e su varie guide che potrete trovare su internet. + +La prima cosa da fare prima di usarlo per produrre patch che saranno +disponibili ad altri, è quella di leggere i siti qui sopra e di acquisire una +base solida su come funziona git. Uno sviluppatore che sappia usare git +dovrebbe essere capace di ottenere una copia del repositorio principale, +esplorare la storia della revisione, registrare le modifiche, usare i rami, +eccetera. Una certa comprensione degli strumenti git per riscrivere la storia +(come ``rebase``) è altrettanto utile. Git ha i propri concetti e la propria +terminologia; un nuovo utente dovrebbe conoscere *refs*, *remote branch*, +*index*, *fast-forward merge*, *push* e *pull*, *detached head*, eccetera. +Il tutto potrebbe essere un po' intimidatorio visto da fuori, ma con un po' +di studio i concetti non saranno così difficili da capire. + +Utilizzare git per produrre patch da sottomettere via email può essere +un buon esercizio da fare mentre si sta prendendo confidenza con lo strumento. + +Quando sarete in grado di creare rami git che siano guardabili da altri, +vi servirà, ovviamente, un server dal quale sia possibile attingere le vostre +modifiche. Se avete un server accessibile da Internet, configurarlo per +eseguire git-daemon è relativamente semplice . Altrimenti, iniziano a +svilupparsi piattaforme che offrono spazi pubblici, e gratuiti (Github, +per esempio). Gli sviluppatori permanenti possono ottenere un account +su kernel.org, ma non è proprio facile da ottenere; per maggiori informazioni +consultate la pagina web http://kernel.org/faq/. + +In git è normale avere a che fare con tanti rami. Ogni linea di sviluppo +può essere separata in "rami per argomenti" e gestiti indipendentemente. +In git i rami sono facilissimi, per cui non c'è motivo per non usarli +in libertà. In ogni caso, non dovreste sviluppare su alcun ramo dal +quale altri potrebbero attingere. I rami disponibili pubblicamente dovrebbero +essere creati con attenzione; integrate patch dai rami di sviluppo +solo quando sono complete e pronte ad essere consegnate - non prima. + +Git offre alcuni strumenti che vi permettono di riscrivere la storia del +vostro sviluppo. Una modifica errata (diciamo, una che rompe la bisezione, +oppure che ha un qualche tipo di baco evidente) può essere corretta sul posto +o fatta sparire completamente dalla storia. Una serie di patch può essere +riscritta come se fosse stata scritta in cima al ramo principale di oggi, +anche se ci avete lavorato per mesi. Le modifiche possono essere spostate +in modo trasparente da un ramo ad un altro. E così via. Un uso giudizioso +di git per revisionare la storia può aiutare nella creazione di una serie +di patch pulite e con meno problemi. + +Un uso eccessivo può portare ad altri tipi di problemi, tuttavia, oltre +alla semplice ossessione per la creazione di una storia del progetto che sia +perfetta. Riscrivere la storia riscriverà le patch contenute in quella +storia, trasformando un kernel verificato (si spera) in uno da verificare. +Ma, oltre a questo, gli sviluppatori non possono collaborare se non condividono +la stessa vista sulla storia del progetto; se riscrivete la storia dalla quale +altri sviluppatori hanno attinto per i loro repositori, renderete la loro vita +molto più difficile. Quindi tenete conto di questa semplice regola generale: +la storia che avete esposto ad altri, generalmente, dovrebbe essere vista come +immutabile. + +Dunque, una volta che il vostro insieme di patch è stato reso disponibile +pubblicamente non dovrebbe essere più sovrascritto. Git tenterà di imporre +questa regola, e si rifiuterà di pubblicare nuove patch che non risultino +essere dirette discendenti di quelle pubblicate in precedenza (in altre parole, +patch che non condividono la stessa storia). È possibile ignorare questo +controllo, e ci saranno momenti in cui sarà davvero necessario riscrivere +un ramo già pubblicato. Un esempio è linux-next dove le patch vengono +spostate da un ramo all'altro al fine di evitare conflitti. Ma questo tipo +d'azione dovrebbe essere un'eccezione. Questo è uno dei motivi per cui lo +sviluppo dovrebbe avvenire in rami privati (che possono essere sovrascritti +quando lo si ritiene necessario) e reso pubblico solo quando è in uno stato +avanzato. + +Man mano che il ramo principale (o altri rami su cui avete basato le +modifiche) avanza, diventa allettante l'idea di integrare tutte le patch +per rimanere sempre aggiornati. Per un ramo privato, il *rebase* può essere +un modo semplice per rimanere aggiornati, ma questa non è un'opzione nel +momento in cui il vostro ramo è stato esposto al mondo intero. +*Merge* occasionali possono essere considerati di buon senso, ma quando +diventano troppo frequenti confondono inutilmente la storia. La tecnica +suggerita in questi casi è quella di fare *merge* raramente, e più in generale +solo nei momenti di rilascio (per esempio gli -rc del ramo principale). +Se siete nervosi circa alcune patch in particolare, potete sempre fare +dei *merge* di test in un ramo privato. In queste situazioni git "rerere" +può essere utile; questo strumento si ricorda come i conflitti di *merge* +furono risolti in passato cosicché non dovrete fare lo stesso lavoro due volte. + +Una delle lamentele più grosse e ricorrenti sull'uso di strumenti come git +è il grande movimento di patch da un repositorio all'altro che rende +facile l'integrazione nel ramo principale di modifiche mediocri, il tutto +sotto il naso dei revisori. Gli sviluppatori del kernel tendono ad essere +scontenti quando vedono succedere queste cose; preparare un ramo git con +patch che non hanno ricevuto alcuna revisione o completamente avulse, potrebbe +influire sulla vostra capacita di proporre, in futuro, l'integrazione dei +vostri rami. Citando Linus + +:: + + Potete inviarmi le vostre patch, ma per far si che io integri una + vostra modifica da git, devo sapere che voi sappiate cosa state + facendo, e ho bisogno di fidarmi *senza* dover passare tutte + le modifiche manualmente una per una. + +(http://lwn.net/Articles/224135/). + +Per evitare queste situazioni, assicuratevi che tutte le patch in un ramo +siano strettamente correlate al tema delle modifiche; un ramo "driver fixes" +non dovrebbe fare modifiche al codice principale per la gestione della memoria. +E, più importante ancora, non usate un repositorio git per tentare di +evitare il processo di revisione. Pubblicate un sommario di quello che il +vostro ramo contiene sulle liste di discussione più opportune, e , quando +sarà il momento, richiedete che il vostro ramo venga integrato in linux-next. + +Se e quando altri inizieranno ad inviarvi patch per essere incluse nel +vostro repositorio, non dovete dimenticare di revisionarle. Inoltre +assicuratevi di mantenerne le informazioni di paternità; al riguardo git "am" +fa del suo meglio, ma potreste dover aggiungere una riga "From:" alla patch +nel caso in cui sia arrivata per vie traverse. + +Quando richiedete l'integrazione, siate certi di fornire tutte le informazioni: +dov'è il vostro repositorio, quale ramo integrare, e quali cambiamenti si +otterranno dall'integrazione. Il comando git request-pull può essere d'aiuto; +preparerà una richiesta nel modo in cui gli altri sviluppatori se l'aspettano, +e verificherà che vi siate ricordati di pubblicare quelle patch su un +server pubblico. + +Revisionare le patch +-------------------- + +Alcuni lettori potrebbero avere obiezioni sulla presenza di questa sezione +negli "argomenti avanzati" sulla base che anche gli sviluppatori principianti +dovrebbero revisionare le patch. É certamente vero che non c'è modo +migliore di imparare come programmare per il kernel che guardare il codice +pubblicato dagli altri. In aggiunta, i revisori sono sempre troppo pochi; +guardando il codice potete apportare un significativo contributo all'intero +processo. + +Revisionare il codice potrebbe risultare intimidatorio, specialmente per i +nuovi arrivati che potrebbero sentirsi un po' nervosi nel questionare +il codice - in pubblico - pubblicato da sviluppatori più esperti. Perfino +il codice scritto dagli sviluppatori più esperti può essere migliorato. +Forse il suggerimento migliore per i revisori (tutti) è questo: formulate +i commenti come domande e non come critiche. Chiedere "Come viene rilasciato +il *lock* in questo percorso?" funziona sempre molto meglio che +"qui la sincronizzazione è sbagliata". + +Diversi sviluppatori revisioneranno il codice con diversi punti di vista. +Alcuni potrebbero concentrarsi principalmente sullo stile del codice e se +alcune linee hanno degli spazio bianchi di troppo. Altri si chiederanno +se accettare una modifica interamente è una cosa positiva per il kernel +o no. E altri ancora si focalizzeranno sui problemi di sincronizzazione, +l'uso eccessivo di *stack*, problemi di sicurezza, duplicazione del codice +in altri contesti, documentazione, effetti negativi sulle prestazioni, cambi +all'ABI dello spazio utente, eccetera. Qualunque tipo di revisione è ben +accetta e di valore, se porta ad avere un codice migliore nel kernel. diff --git a/Documentation/translations/it_IT/process/8.Conclusion.rst b/Documentation/translations/it_IT/process/8.Conclusion.rst new file mode 100644 index 000000000..32659ff46 --- /dev/null +++ b/Documentation/translations/it_IT/process/8.Conclusion.rst @@ -0,0 +1,84 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/8.Conclusion.rst ` +:Translator: Alessia Mantegazza + +.. _it_development_conclusion: + +Per maggiori informazioni +========================= + +Esistono numerose fonti di informazioni sullo sviluppo del kernel Linux +e argomenti correlati. Primo tra questi sarà sempre la cartella Documentation +che si trova nei sorgenti kernel. + +Il file :ref:`process/howto.rst ` è un punto di partenza +importante; :ref:`process/submitting-patches.rst ` è +anch'esso qualcosa che tutti gli sviluppatori del kernel dovrebbero leggere. +Molte API interne al kernel sono documentate utilizzando il meccanismo +kerneldoc; "make htmldocs" o "make pdfdocs" possono essere usati per generare +quei documenti in HTML o PDF (sebbene le versioni di TeX di alcune +distribuzioni hanno dei limiti interni e fallisce nel processare +appropriatamente i documenti). + +Diversi siti web approfondiscono lo sviluppo del kernel ad ogni livello +di dettaglio. Il vostro autore vorrebbe umilmente suggerirvi +http://lwn.net/ come fonte; usando l'indice 'kernel' su LWN troverete +molti argomenti specifici sul kernel: + + http://lwn.net/Kernel/Index/ + +Oltre a ciò, una risorsa valida per gli sviluppatori kernel è: + + http://kernelnewbies.org/ + +E, ovviamente, una fonte da non dimenticare è http://kernel.org/, il luogo +definitivo per le informazioni sui rilasci del kernel. + +Ci sono numerosi libri sullo sviluppo del kernel: + + Linux Device Drivers, 3rd Edition (Jonathan Corbet, Alessandro + Rubini, and Greg Kroah-Hartman). In linea all'indirizzo + http://lwn.net/Kernel/LDD3/. + + Linux Kernel Development (Robert Love). + + Understanding the Linux Kernel (Daniel Bovet and Marco Cesati). + +Tutti questi libri soffrono di un errore comune: tendono a risultare in un +certo senso obsoleti dal momento che si trovano in libreria da diverso +tempo. Comunque contengono informazioni abbastanza buone. + +La documentazione per git la troverete su: + + http://www.kernel.org/pub/software/scm/git/docs/ + + http://www.kernel.org/pub/software/scm/git/docs/user-manual.html + + + +Conclusioni +=========== + +Congratulazioni a chiunque ce l'abbia fatta a terminare questo documento di +lungo-respiro. Si spera che abbia fornito un'utile comprensione d'insieme +di come il kernel Linux viene sviluppato e di come potete partecipare a +tale processo. + +Infine, quello che conta è partecipare. Qualsiasi progetto software +open-source non è altro che la somma di quello che i suoi contributori +mettono al suo interno. Il kernel Linux è cresciuto velocemente e bene +perché ha ricevuto il supporto di un impressionante gruppo di sviluppatori, +ognuno dei quali sta lavorando per renderlo migliore. Il kernel è un esempio +importante di cosa può essere fatto quando migliaia di persone lavorano +insieme verso un obiettivo comune. + +Il kernel può sempre beneficiare di una larga base di sviluppatori, tuttavia, +c'è sempre molto lavoro da fare. Ma, cosa non meno importante, molti degli +altri partecipanti all'ecosistema Linux possono trarre beneficio attraverso +il contributo al kernel. Inserire codice nel ramo principale è la chiave +per arrivare ad una qualità del codice più alta, bassa manutenzione e +bassi prezzi di distribuzione, alti livelli d'influenza sulla direzione +dello sviluppo del kernel, e molto altro. È una situazione nella quale +tutti coloro che sono coinvolti vincono. Mollate il vostro editor e +raggiungeteci; sarete più che benvenuti. diff --git a/Documentation/translations/it_IT/process/adding-syscalls.rst b/Documentation/translations/it_IT/process/adding-syscalls.rst new file mode 100644 index 000000000..df8c652d0 --- /dev/null +++ b/Documentation/translations/it_IT/process/adding-syscalls.rst @@ -0,0 +1,643 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/adding-syscalls.rst ` +:Translator: Federico Vaga + +.. _it_addsyscalls: + +Aggiungere una nuova chiamata di sistema +======================================== + +Questo documento descrive quello che è necessario sapere per aggiungere +nuove chiamate di sistema al kernel Linux; questo è da considerarsi come +un'aggiunta ai soliti consigli su come proporre nuove modifiche +:ref:`Documentation/translations/it_IT/process/submitting-patches.rst `. + + +Alternative alle chiamate di sistema +------------------------------------ + +La prima considerazione da fare quando si aggiunge una nuova chiamata di +sistema è quella di valutare le alternative. Nonostante le chiamate di sistema +siano il punto di interazione fra spazio utente e kernel più tradizionale ed +ovvio, esistono altre possibilità - scegliete quella che meglio si adatta alle +vostra interfaccia. + + - Se le operazioni coinvolte possono rassomigliare a quelle di un filesystem, + allora potrebbe avere molto più senso la creazione di un nuovo filesystem o + dispositivo. Inoltre, questo rende più facile incapsulare la nuova + funzionalità in un modulo kernel piuttosto che essere sviluppata nel cuore + del kernel. + + - Se la nuova funzionalità prevede operazioni dove il kernel notifica + lo spazio utente su un avvenimento, allora restituire un descrittore + di file all'oggetto corrispondente permette allo spazio utente di + utilizzare ``poll``/``select``/``epoll`` per ricevere quelle notifiche. + - Tuttavia, le operazioni che non si sposano bene con operazioni tipo + :manpage:`read(2)`/:manpage:`write(2)` dovrebbero essere implementate + come chiamate :manpage:`ioctl(2)`, il che potrebbe portare ad un'API in + un qualche modo opaca. + + - Se dovete esporre solo delle informazioni sul sistema, un nuovo nodo in + sysfs (vedere ``Documentation/filesystems/sysfs.rst``) o + in procfs potrebbe essere sufficiente. Tuttavia, l'accesso a questi + meccanismi richiede che il filesystem sia montato, il che potrebbe non + essere sempre vero (per esempio, in ambienti come namespace/sandbox/chroot). + Evitate d'aggiungere nuove API in debugfs perché questo non viene + considerata un'interfaccia di 'produzione' verso lo spazio utente. + - Se l'operazione è specifica ad un particolare file o descrittore, allora + potrebbe essere appropriata l'aggiunta di un comando :manpage:`fcntl(2)`. + Tuttavia, :manpage:`fcntl(2)` è una chiamata di sistema multiplatrice che + nasconde una notevole complessità, quindi è ottima solo quando la nuova + funzione assomiglia a quelle già esistenti in :manpage:`fcntl(2)`, oppure + la nuova funzionalità è veramente semplice (per esempio, leggere/scrivere + un semplice flag associato ad un descrittore di file). + - Se l'operazione è specifica ad un particolare processo, allora + potrebbe essere appropriata l'aggiunta di un comando :manpage:`prctl(2)`. + Come per :manpage:`fcntl(2)`, questa chiamata di sistema è un complesso + multiplatore quindi è meglio usarlo per cose molto simili a quelle esistenti + nel comando ``prctl`` oppure per leggere/scrivere un semplice flag relativo + al processo. + + +Progettare l'API: pianificare le estensioni +------------------------------------------- + +Una nuova chiamata di sistema diventerà parte dell'API del kernel, e +dev'essere supportata per un periodo indefinito. Per questo, è davvero +un'ottima idea quella di discutere apertamente l'interfaccia sulla lista +di discussione del kernel, ed è altrettanto importante pianificarne eventuali +estensioni future. + +(Nella tabella delle chiamate di sistema sono disseminati esempi dove questo +non fu fatto, assieme ai corrispondenti aggiornamenti - +``eventfd``/``eventfd2``, ``dup2``/``dup3``, ``inotify_init``/``inotify_init1``, +``pipe``/``pipe2``, ``renameat``/``renameat2`` --quindi imparate dalla storia +del kernel e pianificate le estensioni fin dall'inizio) + +Per semplici chiamate di sistema che accettano solo un paio di argomenti, +il modo migliore di permettere l'estensibilità è quello di includere un +argomento *flags* alla chiamata di sistema. Per assicurarsi che i programmi +dello spazio utente possano usare in sicurezza *flags* con diverse versioni +del kernel, verificate se *flags* contiene un qualsiasi valore sconosciuto, +in qual caso rifiutate la chiamata di sistema (con ``EINVAL``):: + + if (flags & ~(THING_FLAG1 | THING_FLAG2 | THING_FLAG3)) + return -EINVAL; + +(Se *flags* non viene ancora utilizzato, verificate che l'argomento sia zero) + +Per chiamate di sistema più sofisticate che coinvolgono un numero più grande di +argomenti, il modo migliore è quello di incapsularne la maggior parte in una +struttura dati che verrà passata per puntatore. Questa struttura potrà +funzionare con future estensioni includendo un campo *size*:: + + struct xyzzy_params { + u32 size; /* userspace sets p->size = sizeof(struct xyzzy_params) */ + u32 param_1; + u64 param_2; + u64 param_3; + }; + +Fintanto che un qualsiasi campo nuovo, diciamo ``param_4``, è progettato per +offrire il comportamento precedente quando vale zero, allora questo permetterà +di gestire un conflitto di versione in entrambe le direzioni: + + - un vecchio kernel può gestire l'accesso di una versione moderna di un + programma in spazio utente verificando che la memoria oltre la dimensione + della struttura dati attesa sia zero (in pratica verificare che + ``param_4 == 0``). + - un nuovo kernel può gestire l'accesso di una versione vecchia di un + programma in spazio utente estendendo la struttura dati con zeri (in pratica + ``param_4 = 0``). + +Vedere :manpage:`perf_event_open(2)` e la funzione ``perf_copy_attr()`` (in +``kernel/events/core.c``) per un esempio pratico di questo approccio. + + +Progettare l'API: altre considerazioni +-------------------------------------- + +Se la vostra nuova chiamata di sistema permette allo spazio utente di fare +riferimento ad un oggetto del kernel, allora questa dovrebbe usare un +descrittore di file per accesso all'oggetto - non inventatevi nuovi tipi di +accesso da spazio utente quando il kernel ha già dei meccanismi e una semantica +ben definita per utilizzare i descrittori di file. + +Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` ritorna un nuovo +descrittore di file, allora l'argomento *flags* dovrebbe includere un valore +equivalente a ``O_CLOEXEC`` per i nuovi descrittori. Questo rende possibile, +nello spazio utente, la chiusura della finestra temporale fra le chiamate a +``xyzzy()`` e ``fcntl(fd, F_SETFD, FD_CLOEXEC)``, dove un inaspettato +``fork()`` o ``execve()`` potrebbe trasferire il descrittore al programma +eseguito (Comunque, resistete alla tentazione di riutilizzare il valore di +``O_CLOEXEC`` dato che è specifico dell'architettura e fa parte di una +enumerazione di flag ``O_*`` che è abbastanza ricca). + +Se la vostra nuova chiamata di sistema ritorna un nuovo descrittore di file, +dovreste considerare che significato avrà l'uso delle chiamate di sistema +della famiglia di :manpage:`poll(2)`. Rendere un descrittore di file pronto +per la lettura o la scrittura è il tipico modo del kernel per notificare lo +spazio utente circa un evento associato all'oggetto del kernel. + +Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` ha un argomento +che è il percorso ad un file:: + + int sys_xyzzy(const char __user *path, ..., unsigned int flags); + +dovreste anche considerare se non sia più appropriata una versione +:manpage:`xyzzyat(2)`:: + + int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags); + +Questo permette più flessibilità su come lo spazio utente specificherà il file +in questione; in particolare, permette allo spazio utente di richiedere la +funzionalità su un descrittore di file già aperto utilizzando il *flag* +``AT_EMPTY_PATH``, in pratica otterremmo gratuitamente l'operazione +:manpage:`fxyzzy(3)`:: + + - xyzzyat(AT_FDCWD, path, ..., 0) is equivalent to xyzzy(path,...) + - xyzzyat(fd, "", ..., AT_EMPTY_PATH) is equivalent to fxyzzy(fd, ...) + +(Per maggiori dettagli sulla logica delle chiamate \*at(), leggete la pagina +man :manpage:`openat(2)`; per un esempio di AT_EMPTY_PATH, leggere la pagina +man :manpage:`fstatat(2)`). + +Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` prevede un parametro +per descrivere uno scostamento all'interno di un file, usate ``loff_t`` come +tipo cosicché scostamenti a 64-bit potranno essere supportati anche su +architetture a 32-bit. + +Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` prevede l'uso di +funzioni riservate, allora dev'essere gestita da un opportuno bit di privilegio +(verificato con una chiamata a ``capable()``), come descritto nella pagina man +:manpage:`capabilities(7)`. Scegliete un bit di privilegio già esistente per +gestire la funzionalità associata, ma evitate la combinazione di diverse +funzionalità vagamente collegate dietro lo stesso bit, in quanto va contro il +principio di *capabilities* di separare i poteri di root. In particolare, +evitate di aggiungere nuovi usi al fin-troppo-generico privilegio +``CAP_SYS_ADMIN``. + +Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` manipola altri +processi oltre a quello chiamato, allora dovrebbe essere limitata (usando +la chiamata ``ptrace_may_access()``) di modo che solo un processo chiamante +con gli stessi permessi del processo in oggetto, o con i necessari privilegi, +possa manipolarlo. + +Infine, state attenti che in alcune architetture non-x86 la vita delle chiamate +di sistema con argomenti a 64-bit viene semplificata se questi argomenti +ricadono in posizioni dispari (pratica, i parametri 1, 3, 5); questo permette +l'uso di coppie contigue di registri a 32-bit. (Questo non conta se gli +argomenti sono parte di una struttura dati che viene passata per puntatore). + + +Proporre l'API +-------------- + +Al fine di rendere le nuove chiamate di sistema di facile revisione, è meglio +che dividiate le modifiche i pezzi separati. Questi dovrebbero includere +almeno le seguenti voci in *commit* distinti (ognuno dei quali sarà descritto +più avanti): + + - l'essenza dell'implementazione della chiamata di sistema, con i prototipi, + i numeri generici, le modifiche al Kconfig e l'implementazione *stub* di + ripiego. + - preparare la nuova chiamata di sistema per un'architettura specifica, + solitamente x86 (ovvero tutti: x86_64, x86_32 e x32). + - un programma di auto-verifica da mettere in ``tools/testing/selftests/`` + che mostri l'uso della chiamata di sistema. + - una bozza di pagina man per la nuova chiamata di sistema. Può essere + scritta nell'email di presentazione, oppure come modifica vera e propria + al repositorio delle pagine man. + +Le proposte di nuove chiamate di sistema, come ogni altro modifica all'API del +kernel, deve essere sottomessa alla lista di discussione +linux-api@vger.kernel.org. + + +Implementazione di chiamate di sistema generiche +------------------------------------------------ + +Il principale punto d'accesso alla vostra nuova chiamata di sistema +:manpage:`xyzzy(2)` verrà chiamato ``sys_xyzzy()``; ma, piuttosto che in modo +esplicito, lo aggiungerete tramite la macro ``SYSCALL_DEFINEn``. La 'n' +indica il numero di argomenti della chiamata di sistema; la macro ha come +argomento il nome della chiamata di sistema, seguito dalle coppie (tipo, nome) +per definire i suoi parametri. L'uso di questa macro permette di avere +i metadati della nuova chiamata di sistema disponibili anche per altri +strumenti. + +Il nuovo punto d'accesso necessita anche del suo prototipo di funzione in +``include/linux/syscalls.h``, marcato come asmlinkage di modo da abbinargli +il modo in cui quelle chiamate di sistema verranno invocate:: + + asmlinkage long sys_xyzzy(...); + +Alcune architetture (per esempio x86) hanno le loro specifiche tabelle di +chiamate di sistema (syscall), ma molte altre architetture condividono una +tabella comune di syscall. Aggiungete alla lista generica la vostra nuova +chiamata di sistema aggiungendo un nuovo elemento alla lista in +``include/uapi/asm-generic/unistd.h``:: + + #define __NR_xyzzy 292 + __SYSCALL(__NR_xyzzy, sys_xyzzy) + +Aggiornate anche il contatore __NR_syscalls di modo che sia coerente con +l'aggiunta della nuove chiamate di sistema; va notato che se più di una nuova +chiamata di sistema viene aggiunga nella stessa finestra di sviluppo, il numero +della vostra nuova syscall potrebbe essere aggiustato al fine di risolvere i +conflitti. + +Il file ``kernel/sys_ni.c`` fornisce le implementazioni *stub* di ripiego che +ritornano ``-ENOSYS``. Aggiungete la vostra nuova chiamata di sistema anche +qui:: + + COND_SYSCALL(xyzzy); + +La vostra nuova funzionalità del kernel, e la chiamata di sistema che la +controlla, dovrebbero essere opzionali. Quindi, aggiungete un'opzione +``CONFIG`` (solitamente in ``init/Kconfig``). Come al solito per le nuove +opzioni ``CONFIG``: + + - Includete una descrizione della nuova funzionalità e della chiamata di + sistema che la controlla. + - Rendete l'opzione dipendente da EXPERT se dev'essere nascosta agli utenti + normali. + - Nel Makefile, rendere tutti i nuovi file sorgenti, che implementano la + nuova funzionalità, dipendenti dall'opzione CONFIG (per esempio + ``obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.o``). + - Controllate due volte che sia possibile generare il kernel con la nuova + opzione CONFIG disabilitata. + +Per riassumere, vi serve un *commit* che includa: + + - un'opzione ``CONFIG``per la nuova funzione, normalmente in ``init/Kconfig`` + - ``SYSCALL_DEFINEn(xyzzy, ...)`` per il punto d'accesso + - il corrispondente prototipo in ``include/linux/syscalls.h`` + - un elemento nella tabella generica in ``include/uapi/asm-generic/unistd.h`` + - *stub* di ripiego in ``kernel/sys_ni.c`` + + +Implementazione delle chiamate di sistema x86 +--------------------------------------------- + +Per collegare la vostra nuova chiamate di sistema alle piattaforme x86, +dovete aggiornate la tabella principale di syscall. Assumendo che la vostra +nuova chiamata di sistema non sia particolarmente speciale (vedere sotto), +dovete aggiungere un elemento *common* (per x86_64 e x32) in +arch/x86/entry/syscalls/syscall_64.tbl:: + + 333 common xyzzy sys_xyzzy + +e un elemento per *i386* ``arch/x86/entry/syscalls/syscall_32.tbl``:: + + 380 i386 xyzzy sys_xyzzy + +Ancora una volta, questi numeri potrebbero essere cambiati se generano +conflitti durante la finestra di integrazione. + + +Chiamate di sistema compatibili (generico) +------------------------------------------ + +Per molte chiamate di sistema, la stessa implementazione a 64-bit può essere +invocata anche quando il programma in spazio utente è a 32-bit; anche se la +chiamata di sistema include esplicitamente un puntatore, questo viene gestito +in modo trasparente. + +Tuttavia, ci sono un paio di situazione dove diventa necessario avere un +livello di gestione della compatibilità per risolvere le differenze di +dimensioni fra 32-bit e 64-bit. + +Il primo caso è quando un kernel a 64-bit supporta anche programmi in spazio +utente a 32-bit, perciò dovrà ispezionare aree della memoria (``__user``) che +potrebbero contenere valori a 32-bit o a 64-bit. In particolar modo, questo +è necessario quando un argomento di una chiamata di sistema è: + + - un puntatore ad un puntatore + - un puntatore ad una struttura dati contenente a sua volta un puntatore + ( ad esempio ``struct iovec __user *``) + - un puntatore ad un tipo intero di dimensione variabile (``time_t``, + ``off_t``, ``long``, ...) + - un puntatore ad una struttura dati contenente un tipo intero di dimensione + variabile. + +Il secondo caso che richiede un livello di gestione della compatibilità è +quando uno degli argomenti di una chiamata a sistema è esplicitamente un tipo +a 64-bit anche su architetture a 32-bit, per esempio ``loff_t`` o ``__u64``. +In questo caso, un valore che arriva ad un kernel a 64-bit da un'applicazione +a 32-bit verrà diviso in due valori a 32-bit che dovranno essere riassemblati +in questo livello di compatibilità. + +(Da notare che non serve questo livello di compatibilità per argomenti che +sono puntatori ad un tipo esplicitamente a 64-bit; per esempio, in +:manpage:`splice(2)` l'argomento di tipo ``loff_t __user *`` non necessita +di una chiamata di sistema ``compat_``) + +La versione compatibile della nostra chiamata di sistema si chiamerà +``compat_sys_xyzzy()``, e viene aggiunta utilizzando la macro +``COMPAT_SYSCALL_DEFINEn()`` (simile a SYSCALL_DEFINEn). Questa versione +dell'implementazione è parte del kernel a 64-bit ma accetta parametri a 32-bit +che trasformerà secondo le necessità (tipicamente, la versione +``compat_sys_`` converte questi valori nello loro corrispondente a 64-bit e +può chiamare la versione ``sys_`` oppure invocare una funzione che implementa +le parti comuni). + +Il punto d'accesso *compat* deve avere il corrispondente prototipo di funzione +in ``include/linux/compat.h``, marcato come asmlinkage di modo da abbinargli +il modo in cui quelle chiamate di sistema verranno invocate:: + + asmlinkage long compat_sys_xyzzy(...); + +Se la chiamata di sistema prevede una struttura dati organizzata in modo +diverso per sistemi a 32-bit e per quelli a 64-bit, diciamo +``struct xyzzy_args``, allora il file d'intestazione +``then the include/linux/compat.h`` deve includere la sua versione +*compatibile* (``struct compat_xyzzy_args``); ogni variabile con +dimensione variabile deve avere il proprio tipo ``compat_`` corrispondente +a quello in ``struct xyzzy_args``. La funzione ``compat_sys_xyzzy()`` +può usare la struttura ``compat_`` per analizzare gli argomenti ricevuti +da una chiamata a 32-bit. + +Per esempio, se avete i seguenti campi:: + + struct xyzzy_args { + const char __user *ptr; + __kernel_long_t varying_val; + u64 fixed_val; + /* ... */ + }; + +nella struttura ``struct xyzzy_args``, allora la struttura +``struct compat_xyzzy_args`` dovrebbe avere:: + + struct compat_xyzzy_args { + compat_uptr_t ptr; + compat_long_t varying_val; + u64 fixed_val; + /* ... */ + }; + +La lista generica delle chiamate di sistema ha bisogno di essere +aggiustata al fine di permettere l'uso della versione *compatibile*; +la voce in ``include/uapi/asm-generic/unistd.h`` dovrebbero usare +``__SC_COMP`` piuttosto di ``__SYSCALL``:: + + #define __NR_xyzzy 292 + __SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy) + +Riassumendo, vi serve: + + - un ``COMPAT_SYSCALL_DEFINEn(xyzzy, ...)`` per il punto d'accesso + *compatibile* + - un prototipo in ``include/linux/compat.h`` + - (se necessario) una struttura di compatibilità a 32-bit in + ``include/linux/compat.h`` + - una voce ``__SC_COMP``, e non ``__SYSCALL``, in + ``include/uapi/asm-generic/unistd.h`` + +Compatibilità delle chiamate di sistema (x86) +--------------------------------------------- + +Per collegare una chiamata di sistema, su un'architettura x86, con la sua +versione *compatibile*, è necessario aggiustare la voce nella tabella +delle syscall. + +Per prima cosa, la voce in ``arch/x86/entry/syscalls/syscall_32.tbl`` prende +un argomento aggiuntivo per indicare che un programma in spazio utente +a 32-bit, eseguito su un kernel a 64-bit, dovrebbe accedere tramite il punto +d'accesso compatibile:: + + 380 i386 xyzzy sys_xyzzy __ia32_compat_sys_xyzzy + +Secondo, dovete capire cosa dovrebbe succedere alla nuova chiamata di sistema +per la versione dell'ABI x32. Qui C'è una scelta da fare: gli argomenti +possono corrisponde alla versione a 64-bit o a quella a 32-bit. + +Se c'è un puntatore ad un puntatore, la decisione è semplice: x32 è ILP32, +quindi gli argomenti dovrebbero corrispondere a quelli a 32-bit, e la voce in +``arch/x86/entry/syscalls/syscall_64.tbl`` sarà divisa cosicché i programmi +x32 eseguano la chiamata *compatibile*:: + + 333 64 xyzzy sys_xyzzy + ... + 555 x32 xyzzy __x32_compat_sys_xyzzy + +Se non ci sono puntatori, allora è preferibile riutilizzare la chiamata di +sistema a 64-bit per l'ABI x32 (e di conseguenza la voce in +arch/x86/entry/syscalls/syscall_64.tbl rimane immutata). + +In ambo i casi, dovreste verificare che i tipi usati dagli argomenti +abbiano un'esatta corrispondenza da x32 (-mx32) al loro equivalente a +32-bit (-m32) o 64-bit (-m64). + + +Chiamate di sistema che ritornano altrove +----------------------------------------- + +Nella maggior parte delle chiamate di sistema, al termine della loro +esecuzione, i programmi in spazio utente riprendono esattamente dal punto +in cui si erano interrotti -- quindi dall'istruzione successiva, con lo +stesso *stack* e con la maggior parte del registri com'erano stati +lasciati prima della chiamata di sistema, e anche con la stessa memoria +virtuale. + +Tuttavia, alcune chiamata di sistema fanno le cose in modo differente. +Potrebbero ritornare ad un punto diverso (``rt_sigreturn``) o cambiare +la memoria in spazio utente (``fork``/``vfork``/``clone``) o perfino +l'architettura del programma (``execve``/``execveat``). + +Per permettere tutto ciò, l'implementazione nel kernel di questo tipo di +chiamate di sistema potrebbero dover salvare e ripristinare registri +aggiuntivi nello *stack* del kernel, permettendo così un controllo completo +su dove e come l'esecuzione dovrà continuare dopo l'esecuzione della +chiamata di sistema. + +Queste saranno specifiche per ogni architettura, ma tipicamente si definiscono +dei punti d'accesso in *assembly* per salvare/ripristinare i registri +aggiuntivi e quindi chiamare il vero punto d'accesso per la chiamata di +sistema. + +Per l'architettura x86_64, questo è implementato come un punto d'accesso +``stub_xyzzy`` in ``arch/x86/entry/entry_64.S``, e la voce nella tabella +di syscall (``arch/x86/entry/syscalls/syscall_64.tbl``) verrà corretta di +conseguenza:: + + 333 common xyzzy stub_xyzzy + +L'equivalente per programmi a 32-bit eseguiti su un kernel a 64-bit viene +normalmente chiamato ``stub32_xyzzy`` e implementato in +``arch/x86/entry/entry_64_compat.S`` con la corrispondente voce nella tabella +di syscall ``arch/x86/entry/syscalls/syscall_32.tbl`` corretta nel +seguente modo:: + + 380 i386 xyzzy sys_xyzzy stub32_xyzzy + +Se una chiamata di sistema necessita di un livello di compatibilità (come +nella sezione precedente), allora la versione ``stub32_`` deve invocare +la versione ``compat_sys_`` piuttosto che quella nativa a 64-bit. In aggiunta, +se l'implementazione dell'ABI x32 è diversa da quella x86_64, allora la sua +voce nella tabella di syscall dovrà chiamare uno *stub* che invoca la versione +``compat_sys_``, + +Per completezza, sarebbe carino impostare una mappatura cosicché +*user-mode* Linux (UML) continui a funzionare -- la sua tabella di syscall +farà riferimento a stub_xyzzy, ma UML non include l'implementazione +in ``arch/x86/entry/entry_64.S`` (perché UML simula i registri eccetera). +Correggerlo è semplice, basta aggiungere una #define in +``arch/x86/um/sys_call_table_64.c``:: + + #define stub_xyzzy sys_xyzzy + + +Altri dettagli +-------------- + +La maggior parte dei kernel tratta le chiamate di sistema allo stesso modo, +ma possono esserci rare eccezioni per le quali potrebbe essere necessario +l'aggiornamento della vostra chiamata di sistema. + +Il sotto-sistema di controllo (*audit subsystem*) è uno di questi casi +speciali; esso include (per architettura) funzioni che classificano alcuni +tipi di chiamate di sistema -- in particolare apertura dei file +(``open``/``openat``), esecuzione dei programmi (``execve``/``exeveat``) +oppure multiplatori di socket (``socketcall``). Se la vostra nuova chiamata +di sistema è simile ad una di queste, allora il sistema di controllo dovrebbe +essere aggiornato. + +Più in generale, se esiste una chiamata di sistema che è simile alla vostra, +vale la pena fare una ricerca con ``grep`` su tutto il kernel per la chiamata +di sistema esistente per verificare che non ci siano altri casi speciali. + + +Verifica +-------- + +Una nuova chiamata di sistema dev'essere, ovviamente, provata; è utile fornire +ai revisori un programma in spazio utente che mostri l'uso della chiamata di +sistema. Un buon modo per combinare queste cose è quello di aggiungere un +semplice programma di auto-verifica in una nuova cartella in +``tools/testing/selftests/``. + +Per una nuova chiamata di sistema, ovviamente, non ci sarà alcuna funzione +in libc e quindi il programma di verifica dovrà invocarla usando ``syscall()``; +inoltre, se la nuova chiamata di sistema prevede un nuova struttura dati +visibile in spazio utente, il file d'intestazione necessario dev'essere +installato al fine di compilare il programma. + +Assicuratevi che il programma di auto-verifica possa essere eseguito +correttamente su tutte le architetture supportate. Per esempio, verificate che +funzioni quando viene compilato per x86_64 (-m64), x86_32 (-m32) e x32 (-mx32). + +Al fine di una più meticolosa ed estesa verifica della nuova funzionalità, +dovreste considerare l'aggiunta di nuove verifica al progetto 'Linux Test', +oppure al progetto xfstests per cambiamenti relativi al filesystem. + + - https://linux-test-project.github.io/ + - git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git + + +Pagine man +---------- + +Tutte le nuove chiamate di sistema dovrebbero avere una pagina man completa, +idealmente usando i marcatori groff, ma anche il puro testo può andare. Se +state usando groff, è utile che includiate nella email di presentazione una +versione già convertita in formato ASCII: semplificherà la vita dei revisori. + +Le pagine man dovrebbero essere in copia-conoscenza verso +linux-man@vger.kernel.org +Per maggiori dettagli, leggere +https://www.kernel.org/doc/man-pages/patches.html + + +Non invocate chiamate di sistema dal kernel +------------------------------------------- + +Le chiamate di sistema sono, come già detto prima, punti di interazione fra +lo spazio utente e il kernel. Perciò, le chiamate di sistema come +``sys_xyzzy()`` o ``compat_sys_xyzzy()`` dovrebbero essere chiamate solo dallo +spazio utente attraverso la tabella syscall, ma non da nessun altro punto nel +kernel. Se la nuova funzionalità è utile all'interno del kernel, per esempio +dev'essere condivisa fra una vecchia e una nuova chiamata di sistema o +dev'essere utilizzata da una chiamata di sistema e la sua variante compatibile, +allora dev'essere implementata come una funzione di supporto +(*helper function*) (per esempio ``ksys_xyzzy()``). Questa funzione potrà +essere chiamata dallo *stub* (``sys_xyzzy()``), dalla variante compatibile +(``compat_sys_xyzzy()``), e/o da altri parti del kernel. + +Sui sistemi x86 a 64-bit, a partire dalla versione v4.17 è un requisito +fondamentale quello di non invocare chiamate di sistema all'interno del kernel. +Esso usa una diversa convenzione per l'invocazione di chiamate di sistema dove +``struct pt_regs`` viene decodificata al volo in una funzione che racchiude +la chiamata di sistema la quale verrà eseguita successivamente. +Questo significa che verranno passati solo i parametri che sono davvero +necessari ad una specifica chiamata di sistema, invece che riempire ogni volta +6 registri del processore con contenuti presi dallo spazio utente (potrebbe +causare seri problemi nella sequenza di chiamate). + +Inoltre, le regole su come i dati possano essere usati potrebbero differire +fra il kernel e l'utente. Questo è un altro motivo per cui invocare +``sys_xyzzy()`` è generalmente una brutta idea. + +Eccezioni a questa regola vengono accettate solo per funzioni d'architetture +che surclassano quelle generiche, per funzioni d'architettura di compatibilità, +o per altro codice in arch/ + + +Riferimenti e fonti +------------------- + + - Articolo di Michael Kerris su LWN sull'uso dell'argomento flags nelle + chiamate di sistema: https://lwn.net/Articles/585415/ + - Articolo di Michael Kerris su LWN su come gestire flag sconosciuti in + una chiamata di sistema: https://lwn.net/Articles/588444/ + - Articolo di Jake Edge su LWN che descrive i limiti degli argomenti a 64-bit + delle chiamate di sistema: https://lwn.net/Articles/311630/ + - Una coppia di articoli di David Drysdale che descrivono i dettagli del + percorso implementativo di una chiamata di sistema per la versione v3.14: + + - https://lwn.net/Articles/604287/ + - https://lwn.net/Articles/604515/ + + - Requisiti specifici alle architetture sono discussi nella pagina man + :manpage:`syscall(2)` : + http://man7.org/linux/man-pages/man2/syscall.2.html#NOTES + - Collezione di email di Linux Torvalds sui problemi relativi a ``ioctl()``: + http://yarchive.net/comp/linux/ioctl.html + - "Come non inventare interfacce del kernel", Arnd Bergmann, + http://www.ukuug.org/events/linux2007/2007/papers/Bergmann.pdf + - Articolo di Michael Kerris su LWN sull'evitare nuovi usi di CAP_SYS_ADMIN: + https://lwn.net/Articles/486306/ + - Raccomandazioni da Andrew Morton circa il fatto che tutte le informazioni + su una nuova chiamata di sistema dovrebbero essere contenute nello stesso + filone di discussione di email: https://lore.kernel.org/r/20140724144747.3041b208832bbdf9fbce5d96@linux-foundation.org + - Raccomandazioni da Michael Kerrisk circa il fatto che le nuove chiamate di + sistema dovrebbero avere una pagina man: https://lore.kernel.org/r/CAKgNAkgMA39AfoSoA5Pe1r9N+ZzfYQNvNPvcRN7tOvRb8+v06Q@mail.gmail.com + - Consigli da Thomas Gleixner sul fatto che il collegamento all'architettura + x86 dovrebbe avvenire in un *commit* differente: + https://lore.kernel.org/r/alpine.DEB.2.11.1411191249560.3909@nanos + - Consigli da Greg Kroah-Hartman circa la bontà d'avere una pagina man e un + programma di auto-verifica per le nuove chiamate di sistema: + https://lore.kernel.org/r/20140320025530.GA25469@kroah.com + - Discussione di Michael Kerrisk sulle nuove chiamate di sistema contro + le estensioni :manpage:`prctl(2)`: https://lore.kernel.org/r/CAHO5Pa3F2MjfTtfNxa8LbnkeeU8=YJ+9tDqxZpw7Gz59E-4AUg@mail.gmail.com + - Consigli da Ingo Molnar che le chiamate di sistema con più argomenti + dovrebbero incapsularli in una struttura che includa un argomento + *size* per garantire l'estensibilità futura: + https://lore.kernel.org/r/20150730083831.GA22182@gmail.com + - Un certo numero di casi strani emersi dall'uso (riuso) dei flag O_*: + + - commit 75069f2b5bfb ("vfs: renumber FMODE_NONOTIFY and add to uniqueness + check") + - commit 12ed2e36c98a ("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc + conflict") + - commit bb458c644a59 ("Safer ABI for O_TMPFILE") + + - Discussion from Matthew Wilcox about restrictions on 64-bit arguments: + https://lore.kernel.org/r/20081212152929.GM26095@parisc-linux.org + - Raccomandazioni da Greg Kroah-Hartman sul fatto che i flag sconosciuti dovrebbero + essere controllati: https://lore.kernel.org/r/20140717193330.GB4703@kroah.com + - Raccomandazioni da Linus Torvalds che le chiamate di sistema x32 dovrebbero + favorire la compatibilità con le versioni a 64-bit piuttosto che quelle a 32-bit: + https://lore.kernel.org/r/CA+55aFxfmwfB7jbbrXxa=K7VBYPfAvmu3XOkGrLbB1UFjX1+Ew@mail.gmail.com diff --git a/Documentation/translations/it_IT/process/applying-patches.rst b/Documentation/translations/it_IT/process/applying-patches.rst new file mode 100644 index 000000000..1d30e5cd2 --- /dev/null +++ b/Documentation/translations/it_IT/process/applying-patches.rst @@ -0,0 +1,15 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/applying-patches.rst ` +:Translator: Federico Vaga + +.. _it_applying_patches: + +Applicare patch al kernel Linux ++++++++++++++++++++++++++++++++ + +.. note:: + + Questo documento è obsoleto. Nella maggior parte dei casi, piuttosto + che usare ``patch`` manualmente, vorrete usare Git. Per questo motivo + il documento non verrà tradotto. diff --git a/Documentation/translations/it_IT/process/changes.rst b/Documentation/translations/it_IT/process/changes.rst new file mode 100644 index 000000000..10e0ef9c3 --- /dev/null +++ b/Documentation/translations/it_IT/process/changes.rst @@ -0,0 +1,517 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/changes.rst ` +:Translator: Federico Vaga + +.. _it_changes: + +Requisiti minimi per compilare il kernel +++++++++++++++++++++++++++++++++++++++++ + +Introduzione +============ + +Questo documento fornisce una lista dei software necessari per eseguire questa +versione del kernel. + +Questo documento è basato sul file "Changes" del kernel 2.0.x e quindi le +persone che lo scrissero meritano credito (Jared Mauch, Axel Boldt, +Alessandro Sigala, e tanti altri nella rete). + +Requisiti minimi correnti +************************* + +Prima di pensare d'avere trovato un baco, aggiornate i seguenti programmi +**almeno** alla versione indicata! Se non siete certi della versione che state +usando, il comando indicato dovrebbe dirvelo. + +Questa lista presume che abbiate già un kernel Linux funzionante. In aggiunta, +non tutti gli strumenti sono necessari ovunque; ovviamente, se non avete una +PC Card, per esempio, probabilmente non dovreste preoccuparvi di pcmciautils. + +====================== ================= ======================================== + Programma Versione minima Comando per verificare la versione +====================== ================= ======================================== +GNU C 5.1 gcc --version +Clang/LLVM (optional) 11.0.0 clang --version +GNU make 3.81 make --version +binutils 2.23 ld -v +flex 2.5.35 flex --version +bison 2.0 bison --version +pahole 1.16 pahole --version +util-linux 2.10o fdformat --version +kmod 13 depmod -V +e2fsprogs 1.41.4 e2fsck -V +jfsutils 1.1.3 fsck.jfs -V +reiserfsprogs 3.6.3 reiserfsck -V +xfsprogs 2.6.0 xfs_db -V +squashfs-tools 4.0 mksquashfs -version +btrfs-progs 0.18 btrfsck +pcmciautils 004 pccardctl -V +quota-tools 3.09 quota -V +PPP 2.4.0 pppd --version +nfs-utils 1.0.5 showmount --version +procps 3.2.0 ps --version +udev 081 udevd --version +grub 0.93 grub --version || grub-install --version +mcelog 0.6 mcelog --version +iptables 1.4.2 iptables -V +openssl & libcrypto 1.0.0 openssl version +bc 1.06.95 bc --version +Sphinx\ [#f1]_ 1.7 sphinx-build --version +cpio any cpio --version +====================== ================= ======================================== + +.. [#f1] Sphinx è necessario solo per produrre la documentazione del Kernel + +Compilazione del kernel +*********************** + +GCC +--- + +La versione necessaria di gcc potrebbe variare a seconda del tipo di CPU nel +vostro calcolatore. + +Clang/LLVM (opzionale) +---------------------- + +L'ultima versione di clang e *LLVM utils* (secondo `releases.llvm.org +`_) sono supportati per la generazione del +kernel. Non garantiamo che anche i rilasci più vecchi funzionino, inoltre +potremmo rimuovere gli espedienti che abbiamo implementato per farli +funzionare. Per maggiori informazioni +:ref:`Building Linux with Clang/LLVM `. + +Make +---- + +Per compilare il kernel vi servirà GNU make 3.81 o successivo. + +Binutils +-------- + +Per generare il kernel è necessario avere Binutils 2.23 o superiore. + +pkg-config +---------- + +Il sistema di compilazione, dalla versione 4.18, richiede pkg-config per +verificare l'esistenza degli strumenti kconfig e per determinare le +impostazioni da usare in 'make {g,x}config'. Precedentemente pkg-config +veniva usato ma non verificato o documentato. + +Flex +---- + +Dalla versione 4.16, il sistema di compilazione, durante l'esecuzione, genera +un analizzatore lessicale. Questo richiede flex 2.5.35 o successivo. + +Bison +----- + +Dalla versione 4.16, il sistema di compilazione, durante l'esecuzione, genera +un parsificatore. Questo richiede bison 2.0 o successivo. + +pahole +------ + +Dalla versione 5.2, quando viene impostato CONFIG_DEBUG_INFO_BTF, il sistema di +compilazione genera BTF (BPF Type Format) a partire da DWARF per vmlinux. Più +tardi anche per i moduli. Questo richiede pahole v1.16 o successivo. + +A seconda della distribuzione, lo si può trovare nei pacchetti 'dwarves' o +'pahole'. Oppure lo si può trovare qui: https://fedorapeople.org/~acme/dwarves/. + +Perl +---- + +Per compilare il kernel vi servirà perl 5 e i seguenti moduli ``Getopt::Long``, +``Getopt::Std``, ``File::Basename``, e ``File::Find``. + +BC +-- + +Vi servirà bc per compilare i kernel dal 3.10 in poi. + +OpenSSL +------- + +Il programma OpenSSL e la libreria crypto vengono usati per la firma dei moduli +e la gestione dei certificati; sono usati per la creazione della chiave e +la generazione della firma. + +Se la firma dei moduli è abilitata, allora vi servirà openssl per compilare il +kernel 3.7 e successivi. Vi serviranno anche i pacchetti di sviluppo di +openssl per compilare il kernel 4.3 o successivi. + + +Strumenti di sistema +******************** + +Modifiche architetturali +------------------------ + +DevFS è stato reso obsoleto da udev +(http://www.kernel.org/pub/linux/utils/kernel/hotplug/) + +Il supporto per UID a 32-bit è ora disponibile. Divertitevi! + +La documentazione delle funzioni in Linux è una fase di transizione +verso una documentazione integrata nei sorgenti stessi usando dei commenti +formattati in modo speciale e posizionati vicino alle funzioni che descrivono. +Al fine di arricchire la documentazione, questi commenti possono essere +combinati con i file ReST presenti in Documentation/; questi potranno +poi essere convertiti in formato PostScript, HTML, LaTex, ePUB o PDF. +Per convertire i documenti da ReST al formato che volete, avete bisogno di +Sphinx. + +Util-linux +---------- + +Le versioni più recenti di util-linux: forniscono il supporto a ``fdisk`` per +dischi di grandi dimensioni; supportano le nuove opzioni di mount; riconoscono +più tipi di partizioni; hanno un fdformat che funziona con i kernel 2.4; +e altre chicche. Probabilmente vorrete aggiornarlo. + +Ksymoops +-------- + +Se l'impensabile succede e il kernel va in oops, potrebbe servirvi lo strumento +ksymoops per decodificarlo, ma nella maggior parte dei casi non vi servirà. +Generalmente è preferibile compilare il kernel con l'opzione ``CONFIG_KALLSYMS`` +cosicché venga prodotto un output più leggibile che può essere usato così com'è +(produce anche un output migliore di ksymoops). Se per qualche motivo il +vostro kernel non è stato compilato con ``CONFIG_KALLSYMS`` e non avete modo di +ricompilarlo e riprodurre l'oops con quell'opzione abilitata, allora potete +usare ksymoops per decodificare l'oops. + +Mkinitrd +-------- + +I cambiamenti della struttura in ``/lib/modules`` necessita l'aggiornamento di +mkinitrd. + +E2fsprogs +--------- + +L'ultima versione di ``e2fsprogs`` corregge diversi bachi in fsck e debugfs. +Ovviamente, aggiornarlo è una buona idea. + +JFSutils +-------- + +Il pacchetto ``jfsutils`` contiene programmi per il file-system JFS. +Sono disponibili i seguenti strumenti: + +- ``fsck.jfs`` - avvia la ripetizione del log delle transizioni, e verifica e + ripara una partizione formattata secondo JFS + +- ``mkfs.jfs`` - crea una partizione formattata secondo JFS + +- sono disponibili altri strumenti per il file-system. + +Reiserfsprogs +------------- + +Il pacchetto reiserfsprogs dovrebbe essere usato con reiserfs-3.6.x (Linux +kernel 2.4.x). Questo è un pacchetto combinato che contiene versioni +funzionanti di ``mkreiserfs``, ``resize_reiserfs``, ``debugreiserfs`` e +``reiserfsck``. Questi programmi funzionano sulle piattaforme i386 e alpha. + +Xfsprogs +-------- + +L'ultima versione di ``xfsprogs`` contiene, fra i tanti, i programmi +``mkfs.xfs``, ``xfs_db`` e ``xfs_repair`` per il file-system XFS. +Dipendono dell'architettura e qualsiasi versione dalla 2.0.0 in poi +dovrebbe funzionare correttamente con la versione corrente del codice +XFS nel kernel (sono raccomandate le versioni 2.6.0 o successive per via +di importanti miglioramenti). + +PCMCIAutils +----------- + +PCMCIAutils sostituisce ``pcmica-cs``. Serve ad impostare correttamente i +connettori PCMCIA all'avvio del sistema e a caricare i moduli necessari per +i dispositivi a 16-bit se il kernel è stato modularizzato e il sottosistema +hotplug è in uso. + +Quota-tools +----------- + +Il supporto per uid e gid a 32 bit richiedono l'uso della versione 2 del +formato quota. La versione 3.07 e successive di quota-tools supportano +questo formato. Usate la versione raccomandata nella lista qui sopra o una +successiva. + +Micro codice per Intel IA32 +--------------------------- + +Per poter aggiornare il micro codice per Intel IA32, è stato aggiunto un +apposito driver; il driver è accessibile come un normale dispositivo a +caratteri (misc). Se non state usando udev probabilmente sarà necessario +eseguire i seguenti comandi come root prima di poterlo aggiornare:: + + mkdir /dev/cpu + mknod /dev/cpu/microcode c 10 184 + chmod 0644 /dev/cpu/microcode + +Probabilmente, vorrete anche il programma microcode_ctl da usare con questo +dispositivo. + +udev +---- + +``udev`` è un programma in spazio utente il cui scopo è quello di popolare +dinamicamente la cartella ``/dev`` coi dispositivi effettivamente presenti. +``udev`` sostituisce le funzionalità base di devfs, consentendo comunque +nomi persistenti per i dispositivi. + +FUSE +---- + +Serve libfuse 2.4.0 o successiva. Il requisito minimo assoluto è 2.3.0 ma +le opzioni di mount ``direct_io`` e ``kernel_cache`` non funzioneranno. + + +Rete +**** + +Cambiamenti generali +-------------------- + +Se per quanto riguarda la configurazione di rete avete esigenze di un certo +livello dovreste prendere in considerazione l'uso degli strumenti in ip-route2. + +Filtro dei pacchetti / NAT +-------------------------- + +Il codice per filtraggio dei pacchetti e il NAT fanno uso degli stessi +strumenti come nelle versioni del kernel antecedenti la 2.4.x (iptables). +Include ancora moduli di compatibilità per 2.2.x ipchains e 2.0.x ipdwadm. + +PPP +--- + +Il driver per PPP è stato ristrutturato per supportare collegamenti multipli e +per funzionare su diversi livelli. Se usate PPP, aggiornate pppd almeno alla +versione 2.4.0. + +Se non usate udev, dovete avere un file /dev/ppp che può essere creato da root +col seguente comando:: + + mknod /dev/ppp c 108 0 + + +NFS-utils +--------- + +Nei kernel più antichi (2.4 e precedenti), il server NFS doveva essere +informato sui clienti ai quali si voleva fornire accesso via NFS. Questa +informazione veniva passata al kernel quando un cliente montava un file-system +mediante ``mountd``, oppure usando ``exportfs`` all'avvio del sistema. +exportfs prende le informazioni circa i clienti attivi da ``/var/lib/nfs/rmtab``. + +Questo approccio è piuttosto delicato perché dipende dalla correttezza di +rmtab, che non è facile da garantire, in particolare quando si cerca di +implementare un *failover*. Anche quando il sistema funziona bene, ``rmtab`` +ha il problema di accumulare vecchie voci inutilizzate. + +Sui kernel più recenti il kernel ha la possibilità di informare mountd quando +arriva una richiesta da una macchina sconosciuta, e mountd può dare al kernel +le informazioni corrette per l'esportazione. Questo rimuove la dipendenza con +``rmtab`` e significa che il kernel deve essere al corrente solo dei clienti +attivi. + +Per attivare questa funzionalità, dovete eseguire il seguente comando prima di +usare exportfs o mountd:: + + mount -t nfsd nfsd /proc/fs/nfsd + +Dove possibile, raccomandiamo di proteggere tutti i servizi NFS dall'accesso +via internet mediante un firewall. + +mcelog +------ + +Quando ``CONFIG_x86_MCE`` è attivo, il programma mcelog processa e registra +gli eventi *machine check*. Gli eventi *machine check* sono errori riportati +dalla CPU. Incoraggiamo l'analisi di questi errori. + + +Documentazione del kernel +************************* + +Sphinx +------ + +Per i dettaglio sui requisiti di Sphinx, fate riferimento a :ref:`it_sphinx_install` +in :ref:`Documentation/translations/it_IT/doc-guide/sphinx.rst ` + +Ottenere software aggiornato +============================ + +Compilazione del kernel +*********************** + +gcc +--- + +- + +Clang/LLVM +---------- + +- :ref:`Getting LLVM `. + +Make +---- + +- + +Binutils +-------- + +- + +Flex +---- + +- + +Bison +----- + +- + +OpenSSL +------- + +- + +Strumenti di sistema +******************** + +Util-linux +---------- + +- + +Kmod +---- + +- +- + +Ksymoops +-------- + +- + +Mkinitrd +-------- + +- + +E2fsprogs +--------- + +- +- + +JFSutils +-------- + +- + +Reiserfsprogs +------------- + +- + +Xfsprogs +-------- + +- +- + +Pcmciautils +----------- + +- + +Quota-tools +----------- + +- + + +Microcodice Intel P6 +-------------------- + +- + +udev +---- + +- + +FUSE +---- + +- + +mcelog +------ + +- + +cpio +---- + +- + +Rete +**** + +PPP +--- + +- +- +- + + +NFS-utils +--------- + +- + +Iptables +-------- + +- + +Ip-route2 +--------- + +- + +OProfile +-------- + +- + +NFS-Utils +--------- + +- + +Documentazione del kernel +************************* + +Sphinx +------ + +- diff --git a/Documentation/translations/it_IT/process/clang-format.rst b/Documentation/translations/it_IT/process/clang-format.rst new file mode 100644 index 000000000..77eac809a --- /dev/null +++ b/Documentation/translations/it_IT/process/clang-format.rst @@ -0,0 +1,197 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/clang-format.rst ` +:Translator: Federico Vaga + +.. _it_clangformat: + +clang-format +============ +``clang-format`` è uno strumento per formattare codice C/C++/... secondo +un gruppo di regole ed euristiche. Come tutti gli strumenti, non è perfetto +e non copre tutti i singoli casi, ma è abbastanza buono per essere utile. + +``clang-format`` può essere usato per diversi fini: + + - Per riformattare rapidamente un blocco di codice secondo lo stile del + kernel. Particolarmente utile quando si sposta del codice e lo si + allinea/ordina. Vedere it_clangformatreformat_. + + - Identificare errori di stile, refusi e possibili miglioramenti nei + file che mantieni, le modifiche che revisioni, le differenze, + eccetera. Vedere it_clangformatreview_. + + - Ti aiuta a seguire lo stile del codice, particolarmente utile per i + nuovi arrivati o per coloro che lavorano allo stesso tempo su diversi + progetti con stili di codifica differenti. + +Il suo file di configurazione è ``.clang-format`` e si trova nella cartella +principale dei sorgenti del kernel. Le regole scritte in quel file tentano +di approssimare le lo stile di codifica del kernel. Si tenta anche di seguire +il più possibile +:ref:`Documentation/translations/it_IT/process/coding-style.rst `. +Dato che non tutto il kernel segue lo stesso stile, potreste voler aggiustare +le regole di base per un particolare sottosistema o cartella. Per farlo, +potete sovrascriverle scrivendole in un altro file ``.clang-format`` in +una sottocartella. + +Questo strumento è già stato incluso da molto tempo nelle distribuzioni +Linux più popolari. Cercate ``clang-format`` nel vostro repositorio. +Altrimenti, potete scaricare una versione pre-generata dei binari di LLVM/clang +oppure generarlo dai codici sorgenti: + + http://releases.llvm.org/download.html + +Troverete più informazioni ai seguenti indirizzi: + + https://clang.llvm.org/docs/ClangFormat.html + + https://clang.llvm.org/docs/ClangFormatStyleOptions.html + + +.. _it_clangformatreview: + +Revisionare lo stile di codifica per file e modifiche +----------------------------------------------------- + +Eseguendo questo programma, potrete revisionare un intero sottosistema, +cartella o singoli file alla ricerca di errori di stile, refusi o +miglioramenti. + +Per farlo, potete eseguire qualcosa del genere:: + + # Make sure your working directory is clean! + clang-format -i kernel/*.[ch] + +E poi date un'occhiata a *git diff*. + +Osservare le righe di questo diff è utile a migliorare/aggiustare +le opzioni di stile nel file di configurazione; così come per verificare +le nuove funzionalità/versioni di ``clang-format``. + +``clang-format`` è in grado di leggere diversi diff unificati, quindi +potrete revisionare facilmente delle modifiche e *git diff*. +La documentazione si trova al seguente indirizzo: + + https://clang.llvm.org/docs/ClangFormat.html#script-for-patch-reformatting + +Per evitare che ``clang-format`` formatti alcune parti di un file, potete +scrivere nel codice:: + + int formatted_code; + // clang-format off + void unformatted_code ; + // clang-format on + void formatted_code_again; + +Nonostante si attraente l'idea di utilizzarlo per mantenere un file +sempre in sintonia con ``clang-format``, specialmente per file nuovi o +se siete un manutentore, ricordatevi che altre persone potrebbero usare +una versione diversa di ``clang-format`` oppure non utilizzarlo del tutto. +Quindi, dovreste trattenervi dall'usare questi marcatori nel codice del +kernel; almeno finché non vediamo che ``clang-format`` è diventato largamente +utilizzato. + + +.. _it_clangformatreformat: + +Riformattare blocchi di codice +------------------------------ + +Utilizzando dei plugin per il vostro editor, potete riformattare una +blocco (selezione) di codice con una singola combinazione di tasti. +Questo è particolarmente utile: quando si riorganizza il codice, per codice +complesso, macro multi-riga (e allineare le loro "barre"), eccetera. + +Ricordatevi che potete sempre aggiustare le modifiche in quei casi dove +questo strumento non ha fatto un buon lavoro. Ma come prima approssimazione, +può essere davvero molto utile. + +Questo programma si integra con molti dei più popolari editor. Alcuni di +essi come vim, emacs, BBEdit, Visaul Studio, lo supportano direttamente. +Al seguente indirizzo troverete le istruzioni: + + https://clang.llvm.org/docs/ClangFormat.html + +Per Atom, Eclipse, Sublime Text, Visual Studio Code, XCode e altri editor +e IDEs dovreste essere in grado di trovare dei plugin pronti all'uso. + +Per questo caso d'uso, considerate l'uso di un secondo ``.clang-format`` +che potete personalizzare con le vostre opzioni. +Consultare it_clangformatextra_. + + +.. _it_clangformatmissing: + +Cose non supportate +------------------- + +``clang-format`` non ha il supporto per alcune cose che sono comuni nel +codice del kernel. Sono facili da ricordare; quindi, se lo usate +regolarmente, imparerete rapidamente a evitare/ignorare certi problemi. + +In particolare, quelli più comuni che noterete sono: + + - Allineamento di ``#define`` su una singola riga, per esempio:: + + #define TRACING_MAP_BITS_DEFAULT 11 + #define TRACING_MAP_BITS_MAX 17 + #define TRACING_MAP_BITS_MIN 7 + + contro:: + + #define TRACING_MAP_BITS_DEFAULT 11 + #define TRACING_MAP_BITS_MAX 17 + #define TRACING_MAP_BITS_MIN 7 + + - Allineamento dei valori iniziali, per esempio:: + + static const struct file_operations uprobe_events_ops = { + .owner = THIS_MODULE, + .open = probes_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, + .write = probes_write, + }; + + contro:: + + static const struct file_operations uprobe_events_ops = { + .owner = THIS_MODULE, + .open = probes_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, + .write = probes_write, + }; + + +.. _it_clangformatextra: + +Funzionalità e opzioni aggiuntive +--------------------------------- + +Al fine di minimizzare le differenze fra il codice attuale e l'output +del programma, alcune opzioni di stile e funzionalità non sono abilitate +nella configurazione base. In altre parole, lo scopo è di rendere le +differenze le più piccole possibili, permettendo la semplificazione +della revisione di file, differenze e modifiche. + +In altri casi (per esempio un particolare sottosistema/cartella/file), lo +stile del kernel potrebbe essere diverso e abilitare alcune di queste +opzioni potrebbe dare risultati migliori. + +Per esempio: + + - Allineare assegnamenti (``AlignConsecutiveAssignments``). + + - Allineare dichiarazioni (``AlignConsecutiveDeclarations``). + + - Riorganizzare il testo nei commenti (``ReflowComments``). + + - Ordinare gli ``#include`` (``SortIncludes``). + +Piuttosto che per interi file, solitamente sono utili per la riformattazione +di singoli blocchi. In alternativa, potete creare un altro file +``.clang-format`` da utilizzare con il vostro editor/IDE. diff --git a/Documentation/translations/it_IT/process/code-of-conduct.rst b/Documentation/translations/it_IT/process/code-of-conduct.rst new file mode 100644 index 000000000..7dbd7f55f --- /dev/null +++ b/Documentation/translations/it_IT/process/code-of-conduct.rst @@ -0,0 +1,12 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/code-of-conduct.rst ` + +.. _it_code_of_conduct: + +Accordo dei contributori sul codice di condotta ++++++++++++++++++++++++++++++++++++++++++++++++ + +.. warning:: + + TODO ancora da tradurre diff --git a/Documentation/translations/it_IT/process/coding-style.rst b/Documentation/translations/it_IT/process/coding-style.rst new file mode 100644 index 000000000..a393ee418 --- /dev/null +++ b/Documentation/translations/it_IT/process/coding-style.rst @@ -0,0 +1,1213 @@ +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/coding-style.rst ` +:Translator: Federico Vaga + +.. _it_codingstyle: + +Stile del codice per il kernel Linux +==================================== + +Questo è un breve documento che descrive lo stile di codice preferito per +il kernel Linux. Lo stile di codifica è molto personale e non voglio +**forzare** nessuno ad accettare il mio, ma questo stile è quello che +dev'essere usato per qualsiasi cosa che io sia in grado di mantenere, e l'ho +preferito anche per molte altre cose. Per favore, almeno tenete in +considerazione le osservazioni espresse qui. + +La prima cosa che suggerisco è quella di stamparsi una copia degli standard +di codifica GNU e di NON leggerla. Bruciatela, è un grande gesto simbolico. + +Comunque, ecco i punti: + +1) Indentazione +--------------- + +La tabulazione (tab) è di 8 caratteri e così anche le indentazioni. Ci sono +alcuni movimenti di eretici che vorrebbero l'indentazione a 4 (o perfino 2!) +caratteri di profondità, che è simile al tentativo di definire il valore del +pi-greco a 3. + +Motivazione: l'idea dell'indentazione è di definire chiaramente dove un blocco +di controllo inizia e finisce. Specialmente quando siete rimasti a guardare lo +schermo per 20 ore a file, troverete molto più facile capire i livelli di +indentazione se questi sono larghi. + +Ora, alcuni rivendicano che un'indentazione da 8 caratteri sposta il codice +troppo a destra e che quindi rende difficile la lettura su schermi a 80 +caratteri. La risposta a questa affermazione è che se vi servono più di 3 +livelli di indentazione, siete comunque fregati e dovreste correggere il vostro +programma. + +In breve, l'indentazione ad 8 caratteri rende più facile la lettura, e in +aggiunta vi avvisa quando state annidando troppo le vostre funzioni. +Tenete ben a mente questo avviso. + +Al fine di facilitare l'indentazione del costrutto switch, si preferisce +allineare sulla stessa colonna la parola chiave ``switch`` e i suoi +subordinati ``case``. In questo modo si evita una doppia indentazione per +i ``case``. Un esempio.: + +.. code-block:: c + + switch (suffix) { + case 'G': + case 'g': + mem <<= 30; + break; + case 'M': + case 'm': + mem <<= 20; + break; + case 'K': + case 'k': + mem <<= 10; + fallthrough; + default: + break; + } + +A meno che non vogliate nascondere qualcosa, non mettete più istruzioni sulla +stessa riga: + +.. code-block:: c + + if (condition) do_this; + do_something_everytime; + +Non usate le virgole per evitare le parentesi: + +.. code-block:: c + + if (condition) + do_this(), do_that(); + +Invece, usate sempre le parentesi per racchiudere più istruzioni. + +.. code-block:: c + + if (condition) { + do_this(); + do_that(); + } + +Non mettete nemmeno più assegnamenti sulla stessa riga. Lo stile del kernel +è ultrasemplice. Evitate espressioni intricate. + + +Al di fuori dei commenti, della documentazione ed escludendo i Kconfig, gli +spazi non vengono mai usati per l'indentazione, e l'esempio qui sopra è +volutamente errato. + +Procuratevi un buon editor di testo e non lasciate spazi bianchi alla fine +delle righe. + + +2) Spezzare righe lunghe e stringhe +----------------------------------- + +Lo stile del codice riguarda la leggibilità e la manutenibilità utilizzando +strumenti comuni. + +Come limite di riga si preferiscono le 80 colonne. + +Espressioni più lunghe di 80 colonne dovrebbero essere spezzettate in +pezzi più piccoli, a meno che eccedere le 80 colonne non aiuti ad +aumentare la leggibilità senza nascondere informazioni. + +I nuovi pezzi derivati sono sostanzialmente più corti degli originali +e vengono posizionati più a destra. Uno stile molto comune è quello di +allineare i nuovi pezzi alla parentesi aperta di una funzione. + +Lo stesso si applica, nei file d'intestazione, alle funzioni con una +lista di argomenti molto lunga. + +Tuttavia, non spezzettate mai le stringhe visibili agli utenti come i +messaggi di printk, questo perché inibireste la possibilità +d'utilizzare grep per cercarle. + +3) Posizionamento di parentesi graffe e spazi +--------------------------------------------- + +Un altro problema che s'affronta sempre quando si parla di stile in C è +il posizionamento delle parentesi graffe. Al contrario della dimensione +dell'indentazione, non ci sono motivi tecnici sulla base dei quali scegliere +una strategia di posizionamento o un'altra; ma il modo qui preferito, +come mostratoci dai profeti Kernighan e Ritchie, è quello di +posizionare la parentesi graffa di apertura per ultima sulla riga, e quella +di chiusura per prima su una nuova riga, così: + +.. code-block:: c + + if (x is true) { + we do y + } + +Questo è valido per tutte le espressioni che non siano funzioni (if, switch, +for, while, do). Per esempio: + +.. code-block:: c + + switch (action) { + case KOBJ_ADD: + return "add"; + case KOBJ_REMOVE: + return "remove"; + case KOBJ_CHANGE: + return "change"; + default: + return NULL; + } + +Tuttavia, c'è il caso speciale, le funzioni: queste hanno la parentesi graffa +di apertura all'inizio della riga successiva, quindi: + +.. code-block:: c + + int function(int x) + { + body of function + } + +Eretici da tutto il mondo affermano che questa incoerenza è ... +insomma ... incoerente, ma tutte le persone ragionevoli sanno che (a) +K&R hanno **ragione** e (b) K&R hanno ragione. A parte questo, le funzioni +sono comunque speciali (non potete annidarle in C). + +Notate che la graffa di chiusura è da sola su una riga propria, ad +**eccezione** di quei casi dove è seguita dalla continuazione della stessa +espressione, in pratica ``while`` nell'espressione do-while, oppure ``else`` +nell'espressione if-else, come questo: + +.. code-block:: c + + do { + body of do-loop + } while (condition); + +e + +.. code-block:: c + + if (x == y) { + .. + } else if (x > y) { + ... + } else { + .... + } + +Motivazione: K&R. + +Inoltre, notate che questo posizionamento delle graffe minimizza il numero +di righe vuote senza perdere di leggibilità. In questo modo, dato che le +righe sul vostro schermo non sono una risorsa illimitata (pensate ad uno +terminale con 25 righe), avrete delle righe vuote da riempire con dei +commenti. + +Non usate inutilmente le graffe dove una singola espressione è sufficiente. + +.. code-block:: c + + if (condition) + action(); + +e + +.. code-block:: none + + if (condition) + do_this(); + else + do_that(); + +Questo non vale nel caso in cui solo un ramo dell'espressione if-else +contiene una sola espressione; in quest'ultimo caso usate le graffe per +entrambe i rami: + +.. code-block:: c + + if (condition) { + do_this(); + do_that(); + } else { + otherwise(); + } + +Inoltre, usate le graffe se un ciclo contiene più di una semplice istruzione: + +.. code-block:: c + + while (condition) { + if (test) + do_something(); + } + +3.1) Spazi +********** + +Lo stile del kernel Linux per quanto riguarda gli spazi, dipende +(principalmente) dalle funzioni e dalle parole chiave. Usate una spazio dopo +(quasi tutte) le parole chiave. L'eccezioni più evidenti sono sizeof, typeof, +alignof, e __attribute__, il cui aspetto è molto simile a quello delle +funzioni (e in Linux, solitamente, sono usate con le parentesi, anche se il +linguaggio non lo richiede; come ``sizeof info`` dopo aver dichiarato +``struct fileinfo info``). + +Quindi utilizzate uno spazio dopo le seguenti parole chiave:: + + if, switch, case, for, do, while + +ma non con sizeof, typeof, alignof, o __attribute__. Ad esempio, + +.. code-block:: c + + + s = sizeof(struct file); + +Non aggiungete spazi attorno (dentro) ad un'espressione fra parentesi. Questo +esempio è **brutto**: + +.. code-block:: c + + + s = sizeof( struct file ); + +Quando dichiarate un puntatore ad una variabile o una funzione che ritorna un +puntatore, il posto suggerito per l'asterisco ``*`` è adiacente al nome della +variabile o della funzione, e non adiacente al nome del tipo. Esempi: + +.. code-block:: c + + + char *linux_banner; + unsigned long long memparse(char *ptr, char **retptr); + char *match_strdup(substring_t *s); + +Usate uno spazio attorno (da ogni parte) alla maggior parte degli operatori +binari o ternari, come i seguenti:: + + = + - < > * / % | & ^ <= >= == != ? : + +ma non mettete spazi dopo gli operatori unari:: + + & * + - ~ ! sizeof typeof alignof __attribute__ defined + +nessuno spazio dopo l'operatore unario suffisso di incremento o decremento:: + + ++ -- + +nessuno spazio dopo l'operatore unario prefisso di incremento o decremento:: + + ++ -- + +e nessuno spazio attorno agli operatori dei membri di una struttura ``.`` e +``->``. + +Non lasciate spazi bianchi alla fine delle righe. Alcuni editor con +l'indentazione ``furba`` inseriranno gli spazi bianchi all'inizio di una nuova +riga in modo appropriato, quindi potrete scrivere la riga di codice successiva +immediatamente. Tuttavia, alcuni di questi stessi editor non rimuovono +questi spazi bianchi quando non scrivete nulla sulla nuova riga, ad esempio +perché volete lasciare una riga vuota. Il risultato è che finirete per avere +delle righe che contengono spazi bianchi in coda. + +Git vi avviserà delle modifiche che aggiungono questi spazi vuoti di fine riga, +e può opzionalmente rimuoverli per conto vostro; tuttavia, se state applicando +una serie di modifiche, questo potrebbe far fallire delle modifiche successive +perché il contesto delle righe verrà cambiato. + +4) Assegnare nomi +----------------- + +C è un linguaggio spartano, e così dovrebbero esserlo i vostri nomi. Al +contrario dei programmatori Modula-2 o Pascal, i programmatori C non usano +nomi graziosi come ThisVariableIsATemporaryCounter. Un programmatore C +chiamerebbe questa variabile ``tmp``, che è molto più facile da scrivere e +non è una delle più difficili da capire. + +TUTTAVIA, nonostante i nomi con notazione mista siano da condannare, i nomi +descrittivi per variabili globali sono un dovere. Chiamare una funzione +globale ``pippo`` è un insulto. + +Le variabili GLOBALI (da usare solo se vi servono **davvero**) devono avere +dei nomi descrittivi, così come le funzioni globali. Se avete una funzione +che conta gli utenti attivi, dovreste chiamarla ``count_active_users()`` o +qualcosa di simile, **non** dovreste chiamarla ``cntusr()``. + +Codificare il tipo di funzione nel suo nome (quella cosa chiamata notazione +ungherese) è stupido - il compilatore conosce comunque il tipo e +può verificarli, e inoltre confonde i programmatori. + +Le variabili LOCALI dovrebbero avere nomi corti, e significativi. Se avete +un qualsiasi contatore di ciclo, probabilmente sarà chiamato ``i``. +Chiamarlo ``loop_counter`` non è produttivo, non ci sono possibilità che +``i`` possa non essere capito. Analogamente, ``tmp`` può essere una qualsiasi +variabile che viene usata per salvare temporaneamente un valore. + +Se avete paura di fare casino coi nomi delle vostre variabili locali, allora +avete un altro problema che è chiamato sindrome dello squilibrio dell'ormone +della crescita delle funzioni. Vedere il capitolo 6 (funzioni). + +5) Definizione di tipi (typedef) +-------------------------------- + +Per favore non usate cose come ``vps_t``. +Usare il typedef per strutture e puntatori è uno **sbaglio**. Quando vedete: + +.. code-block:: c + + vps_t a; + +nei sorgenti, cosa significa? +Se, invece, dicesse: + +.. code-block:: c + + struct virtual_container *a; + +potreste dire cos'è effettivamente ``a``. + +Molte persone pensano che la definizione dei tipi ``migliori la leggibilità``. +Non molto. Sono utili per: + + (a) gli oggetti completamente opachi (dove typedef viene proprio usato allo + scopo di **nascondere** cosa sia davvero l'oggetto). + + Esempio: ``pte_t`` eccetera sono oggetti opachi che potete usare solamente + con le loro funzioni accessorie. + + .. note:: + Gli oggetti opachi e le ``funzioni accessorie`` non sono, di per se, + una bella cosa. Il motivo per cui abbiamo cose come pte_t eccetera è + che davvero non c'è alcuna informazione portabile. + + (b) i tipi chiaramente interi, dove l'astrazione **aiuta** ad evitare + confusione sul fatto che siano ``int`` oppure ``long``. + + u8/u16/u32 sono typedef perfettamente accettabili, anche se ricadono + nella categoria (d) piuttosto che in questa. + + .. note:: + + Ancora - dev'esserci una **ragione** per farlo. Se qualcosa è + ``unsigned long``, non c'è alcun bisogno di avere: + + typedef unsigned long myfalgs_t; + + ma se ci sono chiare circostanze in cui potrebbe essere ``unsigned int`` + e in altre configurazioni ``unsigned long``, allora certamente typedef + è una buona scelta. + + (c) quando di rado create letteralmente dei **nuovi** tipi su cui effettuare + verifiche. + + (d) circostanze eccezionali, in cui si definiscono nuovi tipi identici a + quelli definiti dallo standard C99. + + Nonostante ci voglia poco tempo per abituare occhi e cervello all'uso dei + tipi standard come ``uint32_t``, alcune persone ne obiettano l'uso. + + Perciò, i tipi specifici di Linux ``u8/u16/u32/u64`` e i loro equivalenti + con segno, identici ai tipi standard, sono permessi- tuttavia, non sono + obbligatori per il nuovo codice. + + (e) i tipi sicuri nella spazio utente. + + In alcune strutture dati visibili dallo spazio utente non possiamo + richiedere l'uso dei tipi C99 e nemmeno i vari ``u32`` descritti prima. + Perciò, utilizziamo __u32 e tipi simili in tutte le strutture dati + condivise con lo spazio utente. + +Magari ci sono altri casi validi, ma la regola di base dovrebbe essere di +non usare MAI MAI un typedef a meno che non rientri in una delle regole +descritte qui. + +In generale, un puntatore, o una struttura a cui si ha accesso diretto in +modo ragionevole, non dovrebbero **mai** essere definite con un typedef. + +6) Funzioni +----------- + +Le funzioni dovrebbero essere brevi e carine, e fare una cosa sola. Dovrebbero +occupare uno o due schermi di testo (come tutti sappiamo, la dimensione +di uno schermo secondo ISO/ANSI è di 80x24), e fare una cosa sola e bene. + +La massima lunghezza di una funziona è inversamente proporzionale alla sua +complessità e al livello di indentazione di quella funzione. Quindi, se avete +una funzione che è concettualmente semplice ma che è implementata come un +lunga (ma semplice) sequenza di caso-istruzione, dove avete molte piccole cose +per molti casi differenti, allora va bene avere funzioni più lunghe. + +Comunque, se avete una funzione complessa e sospettate che uno studente +non particolarmente dotato del primo anno delle scuole superiori potrebbe +non capire cosa faccia la funzione, allora dovreste attenervi strettamente ai +limiti. Usate funzioni di supporto con nomi descrittivi (potete chiedere al +compilatore di renderle inline se credete che sia necessario per le +prestazioni, e probabilmente farà un lavoro migliore di quanto avreste potuto +fare voi). + +Un'altra misura delle funzioni sono il numero di variabili locali. Non +dovrebbero eccedere le 5-10, oppure state sbagliando qualcosa. Ripensate la +funzione, e dividetela in pezzettini. Generalmente, un cervello umano può +seguire facilmente circa 7 cose diverse, di più lo confonderebbe. Lo sai +d'essere brillante, ma magari vorresti riuscire a capire cos'avevi fatto due +settimane prima. + +Nei file sorgenti, separate le funzioni con una riga vuota. Se la funzione è +esportata, la macro **EXPORT** per questa funzione deve seguire immediatamente +la riga della parentesi graffa di chiusura. Ad esempio: + +.. code-block:: c + + int system_is_up(void) + { + return system_state == SYSTEM_RUNNING; + } + EXPORT_SYMBOL(system_is_up); + +6.1) Prototipi di funzione +************************** + +Nei prototipi di funzione, includete i nomi dei parametri e i loro tipi. +Nonostante questo non sia richiesto dal linguaggio C, in Linux viene preferito +perché è un modo semplice per aggiungere informazioni importanti per il +lettore. + +Non usate la parola chiave ``extern`` con le dichiarazioni di funzione perché +rende le righe più lunghe e non è strettamente necessario. + +Quando scrivete i prototipi di funzione mantenete `l'ordine degli elementi `_. + +Prendiamo questa dichiarazione di funzione come esempio:: + + __init void * __must_check action(enum magic value, size_t size, u8 count, + char *fmt, ...) __printf(4, 5) __malloc; + +L'ordine suggerito per gli elementi di un prototipo di funzione è il seguente: + +- classe d'archiviazione (in questo caso ``static __always_inline``. Da notare + che ``__always_inline`` è tecnicamente un attributo ma che viene trattato come + ``inline``) +- attributi della classe di archiviazione (in questo caso ``__init``, in altre + parole la sezione, ma anche cose tipo ``__cold``) +- il tipo di ritorno (in questo caso, ``void *``) +- attributi per il valore di ritorno (in questo caso, ``__must_check``) +- il nome della funzione (in questo caso, ``action``) +- i parametri della funzione(in questo caso, + ``(enum magic value, size_t size, u8 count, char *fmt, ...)``, + da notare che va messo anche il nome del parametro) +- attributi dei parametri (in questo caso, ``__printf(4, 5)``) +- attributi per il comportamento della funzione (in questo caso, ``__malloc_``) + +Notate che per la **definizione** di una funzione (il altre parole il corpo +della funzione), il compilatore non permette di usare gli attributi per i +parametri dopo i parametri. In questi casi, devono essere messi dopo gli +attributi della classe d'archiviazione (notate che la posizione di +``__printf(4,5)`` cambia rispetto alla **dichiarazione**):: + + static __always_inline __init __printf(4, 5) void * __must_check action(enum magic value, + size_t size, u8 count, char *fmt, ...) __malloc + { + ... + }*)**``)**``)``)``*)``)``)``)``*``)``)``)*) + +7) Centralizzare il ritorno delle funzioni +------------------------------------------ + +Sebbene sia deprecata da molte persone, l'istruzione goto è impiegata di +frequente dai compilatori sotto forma di salto incondizionato. + +L'istruzione goto diventa utile quando una funzione ha punti d'uscita multipli +e vanno eseguite alcune procedure di pulizia in comune. Se non è necessario +pulire alcunché, allora ritornate direttamente. + +Assegnate un nome all'etichetta di modo che suggerisca cosa fa la goto o +perché esiste. Un esempio di un buon nome potrebbe essere ``out_free_buffer:`` +se la goto libera (free) un ``buffer``. Evitate l'uso di nomi GW-BASIC come +``err1:`` ed ``err2:``, potreste doverli riordinare se aggiungete o rimuovete +punti d'uscita, e inoltre rende difficile verificarne la correttezza. + +I motivo per usare le goto sono: + +- i salti incondizionati sono più facili da capire e seguire +- l'annidamento si riduce +- si evita di dimenticare, per errore, di aggiornare un singolo punto d'uscita +- aiuta il compilatore ad ottimizzare il codice ridondante ;) + +.. code-block:: c + + int fun(int a) + { + int result = 0; + char *buffer; + + buffer = kmalloc(SIZE, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + if (condition1) { + while (loop1) { + ... + } + result = 1; + goto out_free_buffer; + } + ... + out_free_buffer: + kfree(buffer); + return result; + } + +Un baco abbastanza comune di cui bisogna prendere nota è il ``one err bugs`` +che assomiglia a questo: + +.. code-block:: c + + err: + kfree(foo->bar); + kfree(foo); + return ret; + +Il baco in questo codice è che in alcuni punti d'uscita la variabile ``foo`` è +NULL. Normalmente si corregge questo baco dividendo la gestione dell'errore in +due parti ``err_free_bar:`` e ``err_free_foo:``: + +.. code-block:: c + + err_free_bar: + kfree(foo->bar); + err_free_foo: + kfree(foo); + return ret; + +Idealmente, dovreste simulare condizioni d'errore per verificare i vostri +percorsi d'uscita. + + +8) Commenti +----------- + +I commenti sono una buona cosa, ma c'è anche il rischio di esagerare. MAI +spiegare COME funziona il vostro codice in un commento: è molto meglio +scrivere il codice di modo che il suo funzionamento sia ovvio, inoltre +spiegare codice scritto male è una perdita di tempo. + +Solitamente, i commenti devono dire COSA fa il codice, e non COME lo fa. +Inoltre, cercate di evitare i commenti nel corpo della funzione: se la +funzione è così complessa che dovete commentarla a pezzi, allora dovreste +tornare al punto 6 per un momento. Potete mettere dei piccoli commenti per +annotare o avvisare il lettore circa un qualcosa di particolarmente arguto +(o brutto), ma cercate di non esagerare. Invece, mettete i commenti in +testa alla funzione spiegando alle persone cosa fa, e possibilmente anche +il PERCHÉ. + +Per favore, quando commentate una funzione dell'API del kernel usate il +formato kernel-doc. Per maggiori dettagli, leggete i file in +:ref::ref:`Documentation/translations/it_IT/doc-guide/ ` e in +``script/kernel-doc``. + +Lo stile preferito per i commenti più lunghi (multi-riga) è: + +.. code-block:: c + + /* + * This is the preferred style for multi-line + * comments in the Linux kernel source code. + * Please use it consistently. + * + * Description: A column of asterisks on the left side, + * with beginning and ending almost-blank lines. + */ + +Per i file in net/ e in drivers/net/ lo stile preferito per i commenti +più lunghi (multi-riga) è leggermente diverso. + +.. code-block:: c + + /* The preferred comment style for files in net/ and drivers/net + * looks like this. + * + * It is nearly the same as the generally preferred comment style, + * but there is no initial almost-blank line. + */ + +È anche importante commentare i dati, sia per i tipi base che per tipi +derivati. A questo scopo, dichiarate un dato per riga (niente virgole +per una dichiarazione multipla). Questo vi lascerà spazio per un piccolo +commento per spiegarne l'uso. + + +9) Avete fatto un pasticcio +--------------------------- + +Va bene, li facciamo tutti. Probabilmente vi è stato detto dal vostro +aiutante Unix di fiducia che ``GNU emacs`` formatta automaticamente il +codice C per conto vostro, e avete notato che sì, in effetti lo fa, ma che +i modi predefiniti non sono proprio allettanti (infatti, sono peggio che +premere tasti a caso - un numero infinito di scimmie che scrivono in +GNU emacs non faranno mai un buon programma). + +Quindi, potete sbarazzarvi di GNU emacs, o riconfigurarlo con valori più +sensati. Per fare quest'ultima cosa, potete appiccicare il codice che +segue nel vostro file .emacs: + +.. code-block:: none + + (defun c-lineup-arglist-tabs-only (ignored) + "Line up argument lists by tabs, not spaces" + (let* ((anchor (c-langelem-pos c-syntactic-element)) + (column (c-langelem-2nd-pos c-syntactic-element)) + (offset (- (1+ column) anchor)) + (steps (floor offset c-basic-offset))) + (* (max steps 1) + c-basic-offset))) + + (dir-locals-set-class-variables + 'linux-kernel + '((c-mode . ( + (c-basic-offset . 8) + (c-label-minimum-indentation . 0) + (c-offsets-alist . ( + (arglist-close . c-lineup-arglist-tabs-only) + (arglist-cont-nonempty . + (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only)) + (arglist-intro . +) + (brace-list-intro . +) + (c . c-lineup-C-comments) + (case-label . 0) + (comment-intro . c-lineup-comment) + (cpp-define-intro . +) + (cpp-macro . -1000) + (cpp-macro-cont . +) + (defun-block-intro . +) + (else-clause . 0) + (func-decl-cont . +) + (inclass . +) + (inher-cont . c-lineup-multi-inher) + (knr-argdecl-intro . 0) + (label . -1000) + (statement . 0) + (statement-block-intro . +) + (statement-case-intro . +) + (statement-cont . +) + (substatement . +) + )) + (indent-tabs-mode . t) + (show-trailing-whitespace . t) + )))) + + (dir-locals-set-directory-class + (expand-file-name "~/src/linux-trees") + 'linux-kernel) + +Questo farà funzionare meglio emacs con lo stile del kernel per i file che +si trovano nella cartella ``~/src/linux-trees``. + +Ma anche se doveste fallire nell'ottenere una formattazione sensata in emacs +non tutto è perduto: usate ``indent``. + +Ora, ancora, GNU indent ha la stessa configurazione decerebrata di GNU emacs, +ed è per questo che dovete passargli alcune opzioni da riga di comando. +Tuttavia, non è così terribile, perché perfino i creatori di GNU indent +riconoscono l'autorità di K&R (le persone del progetto GNU non sono cattive, +sono solo mal indirizzate sull'argomento), quindi date ad indent le opzioni +``-kr -i8`` (che significa ``K&R, 8 caratteri di indentazione``), o utilizzate +``scripts/Lindent`` che indenterà usando l'ultimo stile. + +``indent`` ha un sacco di opzioni, e specialmente quando si tratta di +riformattare i commenti dovreste dare un'occhiata alle pagine man. +Ma ricordatevi: ``indent`` non è un correttore per una cattiva programmazione. + +Da notare che potete utilizzare anche ``clang-format`` per aiutarvi con queste +regole, per riformattare rapidamente ad automaticamente alcune parti del +vostro codice, e per revisionare interi file al fine di identificare errori +di stile, refusi e possibilmente anche delle migliorie. È anche utile per +ordinare gli ``#include``, per allineare variabili/macro, per ridistribuire +il testo e altre cose simili. +Per maggiori dettagli, consultate il file +:ref:`Documentation/translations/it_IT/process/clang-format.rst `. + + +10) File di configurazione Kconfig +---------------------------------- + +Per tutti i file di configurazione Kconfig* che si possono trovare nei +sorgenti, l'indentazione è un po' differente. Le linee dopo un ``config`` +sono indentate con un tab, mentre il testo descrittivo è indentato di +ulteriori due spazi. Esempio:: + + config AUDIT + bool "Auditing support" + depends on NET + help + Enable auditing infrastructure that can be used with another + kernel subsystem, such as SELinux (which requires this for + logging of avc messages output). Does not do system-call + auditing without CONFIG_AUDITSYSCALL. + +Le funzionalità davvero pericolose (per esempio il supporto alla scrittura +per certi filesystem) dovrebbero essere dichiarate chiaramente come tali +nella stringa di titolo:: + + config ADFS_FS_RW + bool "ADFS write support (DANGEROUS)" + depends on ADFS_FS + ... + +Per la documentazione completa sui file di configurazione, consultate +il documento Documentation/kbuild/kconfig-language.rst + + +11) Strutture dati +------------------ + +Le strutture dati che hanno una visibilità superiore al contesto del +singolo thread in cui vengono create e distrutte, dovrebbero sempre +avere un contatore di riferimenti. Nel kernel non esiste un +*garbage collector* (e fuori dal kernel i *garbage collector* sono lenti +e inefficienti), questo significa che **dovete** assolutamente avere un +contatore di riferimenti per ogni cosa che usate. + +Avere un contatore di riferimenti significa che potete evitare la +sincronizzazione e permette a più utenti di accedere alla struttura dati +in parallelo - e non doversi preoccupare di una struttura dati che +improvvisamente sparisce dalla loro vista perché il loro processo dormiva +o stava facendo altro per un attimo. + +Da notare che la sincronizzazione **non** si sostituisce al conteggio dei +riferimenti. La sincronizzazione ha lo scopo di mantenere le strutture +dati coerenti, mentre il conteggio dei riferimenti è una tecnica di gestione +della memoria. Solitamente servono entrambe le cose, e non vanno confuse fra +di loro. + +Quando si hanno diverse classi di utenti, le strutture dati possono avere +due livelli di contatori di riferimenti. Il contatore di classe conta +il numero dei suoi utenti, e il contatore globale viene decrementato una +sola volta quando il contatore di classe va a zero. + +Un esempio di questo tipo di conteggio dei riferimenti multi-livello può +essere trovato nella gestore della memoria (``struct mm_sturct``: mm_user e +mm_count), e nel codice dei filesystem (``struct super_block``: s_count e +s_active). + +Ricordatevi: se un altro thread può trovare la vostra struttura dati, e non +avete un contatore di riferimenti per essa, quasi certamente avete un baco. + +12) Macro, enumerati e RTL +--------------------------- + +I nomi delle macro che definiscono delle costanti e le etichette degli +enumerati sono scritte in maiuscolo. + +.. code-block:: c + + #define CONSTANT 0x12345 + +Gli enumerati sono da preferire quando si definiscono molte costanti correlate. + +I nomi delle macro in MAIUSCOLO sono preferibili ma le macro che assomigliano +a delle funzioni possono essere scritte in minuscolo. + +Generalmente, le funzioni inline sono preferibili rispetto alle macro che +sembrano funzioni. + +Le macro che contengono più istruzioni dovrebbero essere sempre chiuse in un +blocco do - while: + +.. code-block:: c + + #define macrofun(a, b, c) \ + do { \ + if (a == 5) \ + do_this(b, c); \ + } while (0) + +Cose da evitare quando si usano le macro: + +1) le macro che hanno effetti sul flusso del codice: + +.. code-block:: c + + #define FOO(x) \ + do { \ + if (blah(x) < 0) \ + return -EBUGGERED; \ + } while (0) + +sono **proprio** una pessima idea. Sembra una chiamata a funzione ma termina +la funzione chiamante; non cercate di rompere il decodificatore interno di +chi legge il codice. + +2) le macro che dipendono dall'uso di una variabile locale con un nome magico: + +.. code-block:: c + + #define FOO(val) bar(index, val) + +potrebbe sembrare una bella cosa, ma è dannatamente confusionario quando uno +legge il codice e potrebbe romperlo con una cambiamento che sembra innocente. + +3) le macro con argomenti che sono utilizzati come l-values; questo potrebbe +ritorcervisi contro se qualcuno, per esempio, trasforma FOO in una funzione +inline. + +4) dimenticatevi delle precedenze: le macro che definiscono espressioni devono +essere racchiuse fra parentesi. State attenti a problemi simili con le macro +parametrizzate. + +.. code-block:: c + + #define CONSTANT 0x4000 + #define CONSTEXP (CONSTANT | 3) + +5) collisione nello spazio dei nomi quando si definisce una variabile locale in +una macro che sembra una funzione: + +.. code-block:: c + + #define FOO(x) \ + ({ \ + typeof(x) ret; \ + ret = calc_ret(x); \ + (ret); \ + }) + +ret è un nome comune per una variabile locale - __foo_ret difficilmente +andrà in conflitto con una variabile già esistente. + +Il manuale di cpp si occupa esaustivamente delle macro. Il manuale di sviluppo +di gcc copre anche l'RTL che viene usato frequentemente nel kernel per il +linguaggio assembler. + +13) Visualizzare i messaggi del kernel +-------------------------------------- + +Agli sviluppatori del kernel piace essere visti come dotti. Tenete un occhio +di riguardo per l'ortografia e farete una belle figura. In inglese, evitate +l'uso incorretto di abbreviazioni come ``dont``: usate ``do not`` oppure +``don't``. Scrivete messaggi concisi, chiari, e inequivocabili. + +I messaggi del kernel non devono terminare con un punto fermo. + +Scrivere i numeri fra parentesi (%d) non migliora alcunché e per questo +dovrebbero essere evitati. + +Ci sono alcune macro per la diagnostica in che dovreste +usare per assicurarvi che i messaggi vengano associati correttamente ai +dispositivi e ai driver, e che siano etichettati correttamente: dev_err(), +dev_warn(), dev_info(), e così via. Per messaggi che non sono associati ad +alcun dispositivo, definisce pr_info(), pr_warn(), pr_err(), +eccetera. + +Tirar fuori un buon messaggio di debug può essere una vera sfida; e quando +l'avete può essere d'enorme aiuto per risolvere problemi da remoto. +Tuttavia, i messaggi di debug sono gestiti differentemente rispetto agli +altri. Le funzioni pr_XXX() stampano incondizionatamente ma pr_debug() no; +essa non viene compilata nella configurazione predefinita, a meno che +DEBUG o CONFIG_DYNAMIC_DEBUG non vengono impostati. Questo vale anche per +dev_dbg() e in aggiunta VERBOSE_DEBUG per aggiungere i messaggi dev_vdbg(). + +Molti sottosistemi hanno delle opzioni di debug in Kconfig che aggiungono +-DDEBUG nei corrispettivi Makefile, e in altri casi aggiungono #define DEBUG +in specifici file. Infine, quando un messaggio di debug dev'essere stampato +incondizionatamente, per esempio perché siete già in una sezione di debug +racchiusa in #ifdef, potete usare printk(KERN_DEBUG ...). + +14) Assegnare memoria +--------------------- + +Il kernel fornisce i seguenti assegnatori ad uso generico: +kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc(), e vzalloc(). +Per maggiori informazioni, consultate la documentazione dell'API: +:ref:`Documentation/translations/it_IT/core-api/memory-allocation.rst ` + +Il modo preferito per passare la dimensione di una struttura è il seguente: + +.. code-block:: c + + p = kmalloc(sizeof(*p), ...); + +La forma alternativa, dove il nome della struttura viene scritto interamente, +peggiora la leggibilità e introduce possibili bachi quando il tipo di +puntatore cambia tipo ma il corrispondente sizeof non viene aggiornato. + +Il valore di ritorno è un puntatore void, effettuare un cast su di esso è +ridondante. La conversione fra un puntatore void e un qualsiasi altro tipo +di puntatore è garantito dal linguaggio di programmazione C. + +Il modo preferito per assegnare un vettore è il seguente: + +.. code-block:: c + + p = kmalloc_array(n, sizeof(...), ...); + +Il modo preferito per assegnare un vettore a zero è il seguente: + +.. code-block:: c + + p = kcalloc(n, sizeof(...), ...); + +Entrambe verificano la condizione di overflow per la dimensione +d'assegnamento n * sizeof(...), se accade ritorneranno NULL. + +Questi allocatori generici producono uno *stack dump* in caso di fallimento +a meno che non venga esplicitamente specificato __GFP_NOWARN. Quindi, nella +maggior parte dei casi, è inutile stampare messaggi aggiuntivi quando uno di +questi allocatori ritornano un puntatore NULL. + +15) Il morbo inline +------------------- + +Sembra che ci sia la percezione errata che gcc abbia una qualche magica +opzione "rendimi più veloce" chiamata ``inline``. In alcuni casi l'uso di +inline è appropriato (per esempio in sostituzione delle macro, vedi +capitolo 12), ma molto spesso non lo è. L'uso abbondante della parola chiave +inline porta ad avere un kernel più grande, che si traduce in un sistema nel +suo complesso più lento per via di una cache per le istruzioni della CPU più +grande e poi semplicemente perché ci sarà meno spazio disponibile per una +pagina di cache. Pensateci un attimo; una fallimento nella cache causa una +ricerca su disco che può tranquillamente richiedere 5 millisecondi. Ci sono +TANTI cicli di CPU che potrebbero essere usati in questi 5 millisecondi. + +Spesso le persone dicono che aggiungere inline a delle funzioni dichiarate +static e utilizzare una sola volta è sempre una scelta vincente perché non +ci sono altri compromessi. Questo è tecnicamente vero ma gcc è in grado di +trasformare automaticamente queste funzioni in inline; i problemi di +manutenzione del codice per rimuovere gli inline quando compare un secondo +utente surclassano il potenziale vantaggio nel suggerire a gcc di fare una +cosa che avrebbe fatto comunque. + +16) Nomi e valori di ritorno delle funzioni +------------------------------------------- + +Le funzioni possono ritornare diversi tipi di valori, e uno dei più comuni +è quel valore che indica se una funzione ha completato con successo o meno. +Questo valore può essere rappresentato come un codice di errore intero +(-Exxx = fallimento, 0 = successo) oppure un booleano di successo +(0 = fallimento, non-zero = successo). + +Mischiare questi due tipi di rappresentazioni è un terreno fertile per +i bachi più insidiosi. Se il linguaggio C includesse una forte distinzione +fra gli interi e i booleani, allora il compilatore potrebbe trovare questi +errori per conto nostro ... ma questo non c'è. Per evitare di imbattersi +in questo tipo di baco, seguite sempre la seguente convenzione:: + + Se il nome di una funzione è un'azione o un comando imperativo, + essa dovrebbe ritornare un codice di errore intero. Se il nome + è un predicato, la funzione dovrebbe ritornare un booleano di + "successo" + +Per esempio, ``add work`` è un comando, e la funzione add_work() ritorna 0 +in caso di successo o -EBUSY in caso di fallimento. Allo stesso modo, +``PCI device present`` è un predicato, e la funzione pci_dev_present() ritorna +1 se trova il dispositivo corrispondente con successo, altrimenti 0. + +Tutte le funzioni esportate (EXPORT) devono rispettare questa convenzione, e +così dovrebbero anche tutte le funzioni pubbliche. Le funzioni private +(static) possono non seguire questa convenzione, ma è comunque raccomandato +che lo facciano. + +Le funzioni il cui valore di ritorno è il risultato di una computazione, +piuttosto che l'indicazione sul successo di tale computazione, non sono +soggette a questa regola. Solitamente si indicano gli errori ritornando un +qualche valore fuori dai limiti. Un tipico esempio è quello delle funzioni +che ritornano un puntatore; queste utilizzano NULL o ERR_PTR come meccanismo +di notifica degli errori. + +17) L'uso di bool +----------------- + +Nel kernel Linux il tipo bool deriva dal tipo _Bool dello standard C99. +Un valore bool può assumere solo i valori 0 o 1, e implicitamente o +esplicitamente la conversione a bool converte i valori in vero (*true*) o +falso (*false*). Quando si usa un tipo bool il costrutto !! non sarà più +necessario, e questo va ad eliminare una certa serie di bachi. + +Quando si usano i valori booleani, dovreste utilizzare le definizioni di true +e false al posto dei valori 1 e 0. + +Per il valore di ritorno delle funzioni e per le variabili sullo stack, l'uso +del tipo bool è sempre appropriato. L'uso di bool viene incoraggiato per +migliorare la leggibilità e spesso è molto meglio di 'int' nella gestione di +valori booleani. + +Non usate bool se per voi sono importanti l'ordine delle righe di cache o +la loro dimensione; la dimensione e l'allineamento cambia a seconda +dell'architettura per la quale è stato compilato. Le strutture che sono state +ottimizzate per l'allineamento o la dimensione non dovrebbero usare bool. + +Se una struttura ha molti valori true/false, considerate l'idea di raggrupparli +in un intero usando campi da 1 bit, oppure usate un tipo dalla larghezza fissa, +come u8. + +Come per gli argomenti delle funzioni, molti valori true/false possono essere +raggruppati in un singolo argomento a bit denominato 'flags'; spesso 'flags' è +un'alternativa molto più leggibile se si hanno valori costanti per true/false. + +Detto ciò, un uso parsimonioso di bool nelle strutture dati e negli argomenti +può migliorare la leggibilità. + +18) Non reinventate le macro del kernel +--------------------------------------- + +Il file di intestazione include/linux/kernel.h contiene un certo numero +di macro che dovreste usare piuttosto che implementarne una qualche variante. +Per esempio, se dovete calcolare la lunghezza di un vettore, sfruttate la +macro: + +.. code-block:: c + + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +Analogamente, se dovete calcolare la dimensione di un qualche campo di una +struttura, usate + +.. code-block:: c + + #define sizeof_field(t, f) (sizeof(((t*)0)->f)) + +Ci sono anche le macro min() e max() che, se vi serve, effettuano un controllo +rigido sui tipi. Sentitevi liberi di leggere attentamente questo file +d'intestazione per scoprire cos'altro è stato definito che non dovreste +reinventare nel vostro codice. + +19) Linee di configurazione degli editor e altre schifezze +----------------------------------------------------------- + +Alcuni editor possono interpretare dei parametri di configurazione integrati +nei file sorgenti e indicati con dai marcatori speciali. Per esempio, emacs +interpreta le linee marcate nel seguente modo: + +.. code-block:: c + + -*- mode: c -*- + +O come queste: + +.. code-block:: c + + /* + Local Variables: + compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c" + End: + */ + +Vim interpreta i marcatori come questi: + +.. code-block:: c + + /* vim:set sw=8 noet */ + +Non includete nessuna di queste cose nei file sorgenti. Le persone hanno le +proprie configurazioni personali per l'editor, e i vostri sorgenti non +dovrebbero sovrascrivergliele. Questo vale anche per i marcatori +d'indentazione e di modalità d'uso. Le persone potrebbero aver configurato una +modalità su misura, oppure potrebbero avere qualche altra magia per far +funzionare bene l'indentazione. + +20) Inline assembly +------------------- + +Nel codice specifico per un'architettura, potreste aver bisogno di codice +*inline assembly* per interfacciarvi col processore o con una funzionalità +specifica della piattaforma. Non esitate a farlo quando è necessario. +Comunque, non usatele gratuitamente quando il C può fare la stessa cosa. +Potete e dovreste punzecchiare l'hardware in C quando è possibile. + +Considerate la scrittura di una semplice funzione che racchiude pezzi comuni +di codice assembler piuttosto che continuare a riscrivere delle piccole +varianti. Ricordatevi che l' *inline assembly* può utilizzare i parametri C. + +Il codice assembler più corposo e non banale dovrebbe andare nei file .S, +coi rispettivi prototipi C definiti nei file d'intestazione. I prototipi C +per le funzioni assembler dovrebbero usare ``asmlinkage``. + +Potreste aver bisogno di marcare il vostro codice asm come volatile al fine +d'evitare che GCC lo rimuova quando pensa che non ci siano effetti collaterali. +Non c'è sempre bisogno di farlo, e farlo quando non serve limita le +ottimizzazioni. + +Quando scrivete una singola espressione *inline assembly* contenente più +istruzioni, mettete ognuna di queste istruzioni in una stringa e riga diversa; +ad eccezione dell'ultima stringa/istruzione, ognuna deve terminare con ``\n\t`` +al fine di allineare correttamente l'assembler che verrà generato: + +.. code-block:: c + + asm ("magic %reg1, #42\n\t" + "more_magic %reg2, %reg3" + : /* outputs */ : /* inputs */ : /* clobbers */); + +21) Compilazione sotto condizione +--------------------------------- + +Ovunque sia possibile, non usate le direttive condizionali del preprocessore +(#if, #ifdef) nei file .c; farlo rende il codice difficile da leggere e da +seguire. Invece, usate queste direttive nei file d'intestazione per definire +le funzioni usate nei file .c, fornendo i relativi stub nel caso #else, +e quindi chiamate queste funzioni senza condizioni di preprocessore. Il +compilatore non produrrà alcun codice per le funzioni stub, produrrà gli +stessi risultati, e la logica rimarrà semplice da seguire. + +È preferibile non compilare intere funzioni piuttosto che porzioni d'esse o +porzioni d'espressioni. Piuttosto che mettere una ifdef in un'espressione, +fattorizzate parte dell'espressione, o interamente, in funzioni e applicate +la direttiva condizionale su di esse. + +Se avete una variabile o funzione che potrebbe non essere usata in alcune +configurazioni, e quindi il compilatore potrebbe avvisarvi circa la definizione +inutilizzata, marcate questa definizione come __maybe_unused piuttosto che +racchiuderla in una direttiva condizionale del preprocessore. (Comunque, +se una variabile o funzione è *sempre* inutilizzata, rimuovetela). + +Nel codice, dov'è possibile, usate la macro IS_ENABLED per convertire i +simboli Kconfig in espressioni booleane C, e quindi usatela nelle classiche +condizioni C: + +.. code-block:: c + + if (IS_ENABLED(CONFIG_SOMETHING)) { + ... + } + +Il compilatore valuterà la condizione come costante (constant-fold), e quindi +includerà o escluderà il blocco di codice come se fosse in un #ifdef, quindi +non ne aumenterà il tempo di esecuzione. Tuttavia, questo permette al +compilatore C di vedere il codice nel blocco condizionale e verificarne la +correttezza (sintassi, tipi, riferimenti ai simboli, eccetera). Quindi +dovete comunque utilizzare #ifdef se il codice nel blocco condizionale esiste +solo quando la condizione è soddisfatta. + +Alla fine di un blocco corposo di #if o #ifdef (più di alcune linee), +mettete un commento sulla stessa riga di #endif, annotando la condizione +che termina. Per esempio: + +.. code-block:: c + + #ifdef CONFIG_SOMETHING + ... + #endif /* CONFIG_SOMETHING */ + +Appendice I) riferimenti +------------------------ + +The C Programming Language, Second Edition +by Brian W. Kernighan and Dennis M. Ritchie. +Prentice Hall, Inc., 1988. +ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback). + +The Practice of Programming +by Brian W. Kernighan and Rob Pike. +Addison-Wesley, Inc., 1999. +ISBN 0-201-61586-X. + +Manuali GNU - nei casi in cui sono compatibili con K&R e questo documento - +per indent, cpp, gcc e i suoi dettagli interni, tutto disponibile qui +http://www.gnu.org/manual/ + +WG14 è il gruppo internazionale di standardizzazione per il linguaggio C, +URL: http://www.open-std.org/JTC1/SC22/WG14/ + +Kernel process/coding-style.rst, by greg@kroah.com at OLS 2002: +http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ diff --git a/Documentation/translations/it_IT/process/deprecated.rst b/Documentation/translations/it_IT/process/deprecated.rst new file mode 100644 index 000000000..febf83897 --- /dev/null +++ b/Documentation/translations/it_IT/process/deprecated.rst @@ -0,0 +1,384 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. include:: ../disclaimer-ita.rst + +:Original: :ref:`Documentation/process/deprecated.rst ` +:Translator: Federico Vaga + +.. _it_deprecated: + +============================================================================== +Interfacce deprecate, caratteristiche del linguaggio, attributi, e convenzioni +============================================================================== + +In un mondo perfetto, sarebbe possibile prendere tutti gli usi di +un'interfaccia deprecata e convertirli in quella nuova, e così sarebbe +possibile rimuovere la vecchia interfaccia in un singolo ciclo di sviluppo. +Tuttavia, per via delle dimensioni del kernel, la gerarchia dei manutentori e +le tempistiche, non è sempre possibile fare questo tipo di conversione tutta +in una volta. Questo significa che nuove istanze di una vecchia interfaccia +potrebbero aggiungersi al kernel proprio quando si sta cercando di rimuoverle, +aumentando così il carico di lavoro. Al fine di istruire gli sviluppatori su +cosa è considerato deprecato (e perché), è stata create la seguente lista a cui +fare riferimento quando qualcuno propone modifiche che usano cose deprecate. + +__deprecated +------------ +Nonostante questo attributo marchi visibilmente un interfaccia come deprecata, +`non produce più alcun avviso durante la compilazione +`_ +perché uno degli obiettivi del kernel è quello di compilare senza avvisi; +inoltre, nessuno stava agendo per rimuovere queste interfacce. Nonostante l'uso +di `__deprecated` in un file d'intestazione sia opportuno per segnare una +interfaccia come 'vecchia', questa non è una soluzione completa. L'interfaccia +deve essere rimossa dal kernel, o aggiunta a questo documento per scoraggiarne +l'uso. + +BUG() e BUG_ON() +---------------- +Al loro posto usate WARN() e WARN_ON() per gestire le +condizioni "impossibili" e gestitele come se fosse possibile farlo. +Nonostante le funzioni della famiglia BUG() siano state progettate +per asserire "situazioni impossibili" e interrompere in sicurezza un +thread del kernel, queste si sono rivelate essere troppo rischiose +(per esempio, in quale ordine rilasciare i *lock*? Ci sono stati che +sono stati ripristinati?). Molto spesso l'uso di BUG() +destabilizza il sistema o lo corrompe del tutto, il che rende +impossibile un'attività di debug o anche solo leggere un rapporto +circa l'errore. Linus ha un'opinione molto critica al riguardo: +`email 1 +`_, +`email 2 +`_ + +Tenete presente che la famiglia di funzioni WARN() dovrebbe essere +usato solo per situazioni che si suppone siano "impossibili". Se +volete avvisare gli utenti riguardo a qualcosa di possibile anche se +indesiderato, usare le funzioni della famiglia pr_warn(). Chi +amministra il sistema potrebbe aver attivato l'opzione sysctl +*panic_on_warn* per essere sicuri che il sistema smetta di funzionare +in caso si verifichino delle condizioni "inaspettate". (per esempio, +date un'occhiata al questo `commit +`_) + +Calcoli codificati negli argomenti di un allocatore +---------------------------------------------------- +Il calcolo dinamico delle dimensioni (specialmente le moltiplicazioni) non +dovrebbero essere fatto negli argomenti di funzioni di allocazione di memoria +(o simili) per via del rischio di overflow. Questo può portare a valori più +piccoli di quelli che il chiamante si aspettava. L'uso di questo modo di +allocare può portare ad un overflow della memoria di heap e altri +malfunzionamenti. (Si fa eccezione per valori numerici per i quali il +compilatore può generare avvisi circa un potenziale overflow. Tuttavia, anche in +questi casi è preferibile riscrivere il codice come suggerito di seguito). + +Per esempio, non usate ``count * size`` come argomento:: + + foo = kmalloc(count * size, GFP_KERNEL); + +Al suo posto, si dovrebbe usare l'allocatore a due argomenti:: + + foo = kmalloc_array(count, size, GFP_KERNEL); + +Nello specifico, kmalloc() può essere sostituta da kmalloc_array(), e kzalloc() +da kcalloc(). + +Se questo tipo di allocatore non è disponibile, allora dovrebbero essere usate +le funzioni del tipo *saturate-on-overflow*:: + + bar = vmalloc(array_size(count, size)); + +Un altro tipico caso da evitare è quello di calcolare la dimensione di una +struttura seguita da un vettore di altre strutture, come nel seguente caso:: + + header = kzalloc(sizeof(*header) + count * sizeof(*header->item), + GFP_KERNEL); + +Invece, usate la seguente funzione:: + + header = kzalloc(struct_size(header, item, count), GFP_KERNEL); + +.. note:: Se per caso state usando struct_size() su una struttura dati che + in coda contiene un array di lunghezza zero o uno, allora siete + invitati a riorganizzare il vostro codice usando il + `flexible array member <#zero-length-and-one-element-arrays>`_. + +Per altri calcoli, usate le funzioni size_mul(), size_add(), e size_sub(). Per +esempio, al posto di:: + + foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL); + +dovreste scrivere: + + foo = krealloc(size_add(current_size, + size_mul(chunk_size, + size_sub(count, 3))), GFP_KERNEL); + +Per maggiori dettagli fate riferimento a array3_size() e flex_array_size(), ma +anche le funzioni della famiglia check_mul_overflow(), check_add_overflow(), +check_sub_overflow(), e check_shl_overflow(). + +simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull() +---------------------------------------------------------------------- +Le funzioni simple_strtol(), simple_strtoll(), +simple_strtoul(), e simple_strtoull() ignorano volutamente +i possibili overflow, e questo può portare il chiamante a generare risultati +inaspettati. Le rispettive funzioni kstrtol(), kstrtoll(), +kstrtoul(), e kstrtoull() sono da considerarsi le corrette +sostitute; tuttavia va notato che queste richiedono che la stringa sia +terminata con il carattere NUL o quello di nuova riga. + +strcpy() +-------- +La funzione strcpy() non fa controlli agli estremi del buffer +di destinazione. Questo può portare ad un overflow oltre i limiti del +buffer e generare svariati tipi di malfunzionamenti. Nonostante l'opzione +`CONFIG_FORTIFY_SOURCE=y` e svariate opzioni del compilatore aiutano +a ridurne il rischio, non c'è alcuna buona ragione per continuare ad usare +questa funzione. La versione sicura da usare è strscpy(), tuttavia va +prestata attenzione a tutti quei casi dove viene usato il valore di +ritorno di strcpy(). La funzione strscpy() non ritorna un puntatore +alla destinazione, ma un contatore dei byte non NUL copiati (oppure +un errno negativo se la stringa è stata troncata). + +strncpy() su stringe terminate con NUL +-------------------------------------- +L'utilizzo di strncpy() non fornisce alcuna garanzia sul fatto che +il buffer di destinazione verrà terminato con il carattere NUL. Questo +potrebbe portare a diversi overflow di lettura o altri malfunzionamenti +causati, appunto, dalla mancanza del terminatore. Questa estende la +terminazione nel buffer di destinazione quando la stringa d'origine è più +corta; questo potrebbe portare ad una penalizzazione delle prestazioni per +chi usa solo stringe terminate. La versione sicura da usare è +strscpy(), tuttavia va prestata attenzione a tutti quei casi dove +viene usato il valore di ritorno di strncpy(). La funzione strscpy() +non ritorna un puntatore alla destinazione, ma un contatore dei byte +non NUL copiati (oppure un errno negativo se la stringa è stata +troncata). Tutti i casi che necessitano di estendere la +terminazione con NUL dovrebbero usare strscpy_pad(). + +Se il chiamate no usa stringhe terminate con NUL, allore strncpy() +può continuare ad essere usata, ma i buffer di destinazione devono essere +marchiati con l'attributo `__nonstring `_ +per evitare avvisi durante la compilazione. + +strlcpy() +--------- +La funzione strlcpy(), per prima cosa, legge interamente il buffer di +origine, magari leggendo più di quanto verrà effettivamente copiato. Questo +è inefficiente e può portare a overflow di lettura quando la stringa non è +terminata con NUL. La versione sicura da usare è strscpy(), tuttavia +va prestata attenzione a tutti quei casi dove viene usato il valore di +ritorno di strlcpy(), dato che strscpy() ritorna un valore di errno +negativo quanto la stringa viene troncata. + +Segnaposto %p nella stringa di formato +-------------------------------------- + +Tradizionalmente, l'uso del segnaposto "%p" nella stringa di formato +esponne un indirizzo di memoria in dmesg, proc, sysfs, eccetera. Per +evitare che questi indirizzi vengano sfruttati da malintenzionati, +tutto gli usi di "%p" nel kernel rappresentano l'hash dell'indirizzo, +rendendolo di fatto inutilizzabile. Nuovi usi di "%p" non dovrebbero +essere aggiunti al kernel. Per una rappresentazione testuale di un +indirizzo usate "%pS", l'output è migliore perché mostrerà il nome del +simbolo. Per tutto il resto, semplicemente non usate "%p". + +Parafrasando la `guida +`_ +di Linus: + +- Se il valore hash di "%p" è inutile, chiediti se il puntatore stesso + è importante. Forse dovrebbe essere rimosso del tutto? +- Se credi davvero che il vero valore del puntatore sia importante, + perché alcuni stati del sistema o i livelli di privilegi di un + utente sono considerati "special"? Se pensi di poterlo giustificare + (in un commento e nel messaggio del commit) abbastanza bene da + affrontare il giudizio di Linus, allora forse potrai usare "%px", + assicurandosi anche di averne il permesso. + +Potete disabilitare temporaneamente l'hashing di "%p" nel caso in cui questa +funzionalità vi sia d'ostacolo durante una sessione di debug. Per farlo +aggiungete l'opzione di debug "`no_hash_pointers +`_" alla +riga di comando del kernel. + +Vettori a dimensione variabile (VLA) +------------------------------------ + +Usare VLA sullo stack produce codice molto peggiore rispetto a quando si usano +vettori a dimensione fissa. Questi `problemi di prestazioni `_, +tutt'altro che banali, sono già un motivo valido per eliminare i VLA; in +aggiunta sono anche un problema per la sicurezza. La crescita dinamica di un +vettore nello stack potrebbe eccedere la memoria rimanente in tale segmento. +Questo può portare a dei malfunzionamenti, potrebbe sovrascrivere +dati importanti alla fine dello stack (quando il kernel è compilato senza +`CONFIG_THREAD_INFO_IN_TASK=y`), o sovrascrivere un pezzo di memoria adiacente +allo stack (quando il kernel è compilato senza `CONFIG_VMAP_STACK=y`). + +Salto implicito nell'istruzione switch-case +------------------------------------------- + +Il linguaggio C permette ai casi di un'istruzione `switch` di saltare al +prossimo caso quando l'istruzione "break" viene omessa alla fine del caso +corrente. Tuttavia questo rende il codice ambiguo perché non è sempre ovvio se +l'istruzione "break" viene omessa intenzionalmente o è un baco. Per esempio, +osservando il seguente pezzo di codice non è chiaro se lo stato +`STATE_ONE` è stato progettato apposta per eseguire anche `STATE_TWO`:: + + switch (value) { + case STATE_ONE: + do_something(); + case STATE_TWO: + do_other(); + break; + default: + WARN("unknown state"); + } + +Dato che c'è stata una lunga lista di problemi `dovuti alla mancanza dell'istruzione +"break" `_, oggigiorno non +permettiamo più che vi sia un "salto implicito" (*fall-through*). Per +identificare un salto implicito intenzionale abbiamo adottato la pseudo +parola chiave 'fallthrough' che viene espansa nell'estensione di gcc +`__attribute__((fallthrough))` `Statement Attributes +`_. +(Quando la sintassi C17/C18 `[[fallthrough]]` sarà più comunemente +supportata dai compilatori C, analizzatori statici, e dagli IDE, +allora potremo usare quella sintassi per la pseudo parola chiave) + +Quando la sintassi [[fallthrough]] sarà più comunemente supportata dai +compilatori, analizzatori statici, e ambienti di sviluppo IDE, +allora potremo usarla anche noi. + +Ne consegue che tutti i blocchi switch/case devono finire in uno dei seguenti +modi: + +* ``break;`` +* `fallthrough;`` +* ``continue;`` +* ``goto