Weblog geek del RofiWeblog amb documentació que considero interessant sobre GNU/Linux i programació en general. URLhttp://rofi.pinchito.com/weblog/index.php?blogId=1Última actualitzaciófa 3 years 7 setmanesMay 19, 200522:17
La gestió dels esdeveniments es realitza de diferents maneres
en els diferents llenguatges de programació existents. Anem
a veure per sobre com es fa en cada un d'ells.
Per gestió d'esdeveniments ens referim a quins mecanismes es poden utilitzar en els diferents llenguatges de programació per a la gestió d'esdeveniments asÃncrons. Quan es tracta de detectar un succés de tipus asÃncron sempre tenim dues alternatives. L'una, anomenada model estirada, consisteix en anar consultant si l'esdeveniment ha succeït. Aquest mètode dóna a lloc a tècniques com ara el polling periòdic. Són solucions que funcionen bé per alguns casos però fan perdre temps ja que sovint suposen comprovacions innecessà ries. L'altra tècnica, anomenada model empenta, consisteix en què quan ha succeït un esdeveniment hi ha algú que ens avisa que ha succeït. Això suposa que l'encarregat d'avisar del succés ens ha de poder avisar, per tant hi ha d'haver una forma de registrar-nos a ell. Sinó no podrà avisar-nos que ha succeït l'event. Aquest model té l'avantatge que no hi ha consultes innecessà ries però a la contra és sempre més complex d'implementar. És un mecanisme força usat i dóna lloc a un patró de disseny propi anomenat patró Subjecte-Observador (es un cas més general d'un altre patró conegut com Model-Vista-Controlador). CallbacksMolts llenguatges disposen del que s'anomena els callbacks. En realitat és una tècnica que es basa en utilitzar un punter a una funció a fi de poder-la cridar des del programa. No només s'utilitza per a la comunicació d'esdeveniments sinó que pot servir com a mecanisme d'abstracció. Per exemple la rutina qsort de ISO C té la següent signatura: void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));El segon parà metre és un punter a una funció que rep un parell d'elements const void* i ens retorna un enter indicant-nos la relació d'ordre que tenen entre ells. Considerem un altre exemple. GTK+ és una llibreria grà fica portable molt utilitzada a GNU/Linux. Observem com podem detectar que s'ha premut un botó (això és un extracte d'un exemple del tutorial de GTK+). static void hola( GtkWidget *widget, gpointer data ) { // No posem accents perquè haurien d'anar en UTF-8 g_print ("Hola mon"); } int main(int argc, char* argv[]) { ... /* Crea un botó amb tÃtol "Premeu-me" */ boto = gtk_button_new_with_label ("Premeu-me"); /* Quan el botó rebi el senyal "clicked" cridarà la funció hola() passant * NULL com a argument. */ g_signal_connect (G_OBJECT (boto), "clicked", G_CALLBACK (hola), NULL); ... }El senyal clicked el llença un botó quan l'usuari fa clic sobre d'ell. En aquest cas el que hem fet és vincular aquest senyal amb una funció callback hola. D'aquesta manera quan l'usuari faci clic al botó aquest cridarà indirectament hola. Tant G_OBJECT com G_CALLBACK són macros de GTK+ que s'encarreguen de fer els casting apropiats perquè el compilador no llenci cap missatge de warning. L'ús de punters a funcions és prà ctic però com sempre té la pega que és arriscat. Passar un punter de funció incorrecte o que no té la signatura adequada pot provocar errors a qui crida la funció. D'altra banda està clar que amb C poca cosa més podrem fer per tant anem a veure quines possibilitats ofereixen d'altres llenguatges. ClassesJa hem vist una forma d'implementar el model empenta. Anem a veure com es pot millorar utilitzant la programació orientada a objectes. El problema principal que ens hem trobat utilitzant punters a funcions és que és fà cil que el punter que passem no apunti a la funció adequada. Mitjançant l'ús de les classes abstractes en C++ i Java podem imposar una interfÃcie. Per exemple, observem el següent exemple de la llibreria d'interfÃcies grà fiques Swing de Java: public class ElMeuPrograma { ... //El codi d'inicialitzacio JButton boto = new JButton("Premeu-me"); boto.addActionListener(new BotoPremut()); } class BotoPremut implements ActionListener { public void actionPerformed(ActionEvent e) { System.out.println("Hola món"); } }A Swing els esdeveniments provenen de event sources i són propagats als event listeners. Fixeu-vos que el mecanisme que hem d'utilitzar és crear una classe i implementar el mètode que rebrà el event. Per als ActionListeners és actionPerformed. Sobré un botó els ActionListeners s'executen quan l'usuari fa clic. Llavors només falta afegir un objecte d'aquesta classe. Ara ja no podem tenir problemes de passar una signatura incorrecta. L'única pega és que necessitarem una classe per cada botó que calgui tractar diferent. A més d'haver de crear un objecte. També cal dir que té els seus avantatges, en ser una classe permet dotar al Listener de cert estat. Signals i slotsSi canviem el nom de event source i event listener per signal i slot tenim l'altra tècnica per implementar esdeveniments de tipus asÃncron. La primera solució que veurem és la que s'utilitza a QT, una altra llibreria de desenvolupament d'interfÃcies grà fiques portable molt utilizada a GNU/Linux. class EnviaSignals : public QObject { private: int numero; public signal: void haCanviatElNumero(int); public: EnviaSignals() : numero(0) { } void incrementaNumero(int increment = 1) { numero += increment; emit haCanviatElNumero(numero); } }; class RepSignals : public QObject { public slot: void aviseuMeQuanCanvii(int numero) { std::cout class Saludador { public: sigc::signal signal_salutacio; Saludador(); void saluda() { // Aixo es el mateix que signal_salutacio.emit() signal_salutacio(); } }; void fer_salutacio() { coutMay 14, 200517:56
Llegint en un article d'una persona que experimentava amb Mono veig
que ha d'instal·lar tot de paquets que la seva distribució no porta. Però aquesta no la forma adequada
de fer les coses.
Sovint els no iniciats a les distribucions de GNU/Linux volen acabar d'instal·lar els programes per a fer-se l'entorn que necessiten. Els distribuïdors i empaquetadors inverteixen temps en empaquetar la majoria de programes de forma que s'integren adequadament amb tot el sistema. En particular les distribucions més grans (tipus Debian, Suse, Red Hat, Mandrake, Gentoo, etc) disposen de paquets (precompilats normalment, tret de Gentoo). Aquests són els paquets que voldrem utilitzar en els nostres sistemes. Però els usuaris novells, segurament perquè no han descobert l'eina d'instal·lació de paquets de la seva distribució, insisteixen a compilar el programa. I clar, sovint no tenen èxit. I és que realment gairebé mai és necessari compilar les nostres aplicacions. Només és raonable fer-ho si volem modificar-les per algun motiu, o la versió que porta la nostra distribució és massa vella o bé no ha estat encara empaquetada pel distribuïdor. En aquest cas s'ha de tenir en compte que cal instal·lar els paquets de desenvolupament de totes les llibreries que requereixi el programa. En particular a Debian són els paquets paquet-dev i a Red Hat, Suse i Mandrake els paquet-devel. Quan ja tinguem les llibreries instal·lades llavors ja podrem fer el clà ssic configure. En particular és recomanable indicar --prefix=/opt/nomprograma aixà tota l'aplicació s'instal·larà dins de /opt/nomprograma i sempre serà més fà cil esborrar-la i localitzar els fitxers. May 12, 200516:17
Un cop ja hem conseguit tenir els usuaris introduïts al LDAP
de forma que es poden autenticar des de qualsevol Linux
anem a veure com conseguir que puguin entrar també des de
Windows utilitzant un domini Windows NT i Samba.Controlador primari de domini
Les xarxes Windows NT es basen en els controladors de domini que són mà quines que duen a terme l'autenticació. Hi ha la possibilitat que siguin primà ries o que facin de backup per si la primà ria ha caigut. Quan hom entra a un Windows que està en un domini i s'autentica amb èxit rep el seu perfil que s'emmagatzema al servidor. Si no en tenia es crea a partir d'un compte de client local Default User. Aquest perfil no és més que el nostre home a Windows i la nostra configuració del registre. En sortir, Windows sincronitza el perfil que tenim localment amb el perfil remot (és en aquest punt on sol fer figa tot : manca d'espai, errors en la sincronització, etc) i deixa una còpia del perfil en aquest ordinador per accelerar un posterior login. És clar que en aquest posterior login pot ser necessari resincronitzar el perfil per si hem entrat des d'una altra mà quina amb Windows. És possible configurar Windows perquè no emmagatzemi una còpia local del perfil i un cop sincronitzada després sortir l'esborri. Això ajuda a reduir problemes amb el perfil de Windows ja que l'etapa de sincronització és crÃtica. Sol fer-se malbé el perfil amb una facilitat extraordinà ria en particular en sistemes amb configuracions no exactament iguals. A més no és qüestió d'anar deixant per tots els ordinadors on has passat una còpia del teu home. És un problema molt greu per als administradors mantenir perfils de mida raonable. Tècnicament si un usuari sol entrar sempre des de la mateixa mà quina la sincronització del perfil és una bona solució. El problema és quan entra des d'una altra mà quina on no hi ha el perfil. Ara toca descarregar-lo tot per la xarxa. La qüestió està en què no és difÃcil, en particular utilitzant Outlook o per la pròpia cache del navegador, que el perfil assoleixi mides de diversos gigabytes. Noteu que, si l'usuari sempre utilitza la mateixa mà quina no ha de ser massa problema perquè la sincronització es pot fer rà pidament, aquest problema és més freqüent en entorns acadèmics on es vol oferir l'accés al sistema des de qualsevol mà quina. No sé si és possible que Windows treballi totalment de forma remota amb el perfil, sà que és factible que treballi totalment de forma local, de forma que podrÃem tenir diferents perfils en diferents mà quines i el controlador de domini bà sicament s'encarregaria de fer l'autenticació. Bé, la idea és que Samba 3.x ens faci de controlador primari de domini operant contra LDAP per emmagatzemar la informació dels usuaris. Preparar LDAP de nouAmb els schema que tenÃem no en tindrem prou per poder desar els usuaris al LDAP. Per tant al fitxer /etc/ldap/slapd.conf haurem d'afegir un schema que porta Samba. El que farem és copiar-lo al directori /etc/ldap/schema. include /etc/ldap/schema/core.schema include /etc/ldap/schema/cosine.schema include /etc/ldap/schema/nis.schema include /etc/ldap/schema/inetorgperson.schema include /etc/ldap/schema/samba.schemaAra en la nostra base de dades d'usuaris afegirem uns quants Ãndexos perquè LDAP pugui respondre més rà pid algunes consultes i afegirem alguna opcio de seguretat. database ldbm suffix "dc=pigonet" # ... la resta d'opcions # Ã?ndexos index objectClass eq index cn,uid eq index uidNumber eq index gidNumber eq index sambaSID eq index sambaPrimaryGroupSID eq index sambaDomainName eq # ... la resta del fitxer # Nova restricció de seguretat access to attrs=SambaLMPassword,SambaNTPassword by dn="cn=admin,dc=pigonet" write by * noneCom sempre, apaguem el servidor, reindexem i el reiniciem. # /etc/init.d/slapd stop # slapindex # /etc/init.d/slapd startPerquè tot pugui acabar funcionat ens faltarà disposar d'un lloc on desarem els comptes de confiança de les mà quines. Per fer-ho afegirem el següent LDIF al LDAP. $ cat maquines.ldif dn: ou=maquines,dc=pigonet ou: maquines objectClass: organizationalUnit $ ldapadd -x -W -f maquines.ldif -D cn=admin,dc=pigonet Password: (added new entry "ou=maquines,dc=pigonet") Configurar Samba per fer PDC i utilitzar LDAPPrimer configurarem Samba perquè pugui actuar de controlador primari del domini Windows NT (PDC). Per fer-ho configurarem el fitxer /etc/samba/smb.conf. La següent és una configuració mÃnima on només falta la informació de LDAP. [global] ## Browsing/Identification ### # Nom del DOMINI windows workgroup = SMBFERRER # Nom d'aquesta mà quina, hauria de coincidir amb la del host netbios name = tiresies # Com s'anuncia aquest servidor server string = %h PDC (Samba %v) # Configuració per a un PDC preferred master = yes local master = yes domain master = yes domain logons = yes wins support = no # Tothom s'oblida d'això i llavors # els fitxers queden desats com UTF-8 # al servidor i no ho volem! unix charset = ISO-8859-1 display charset = ISO-8859-1 # Aquest és el tipus de segurat que # es necessita per a un PDC security = user encrypt passwords = true # LDAP # Després afegirem informació per al LDAP [homes] comment = Homes dels usuaris read> Quant a la part de LDAP caldrà indicar a Samba 3 que volem que utilitzi el LDAP per desar tot el que li calgui. I llavors indicarem en quins punts del directori trobarà els diferents elements. # LDAP # Sufix del nostre directori ldap suffix = dc=pigonet # DN de l'administrador ldap admin dn = cn=admin,dc=pigonet # No volem SSL, tot i que seria recomanable en # un entorn més segur ldap ssl = No # On volem que operi Samba passdb backend = ldapsam:ldap://localhost # Ara els diferents DN relatius al "ldap suffix" ldap user suffix = ou=usuaris ldap group suffix = ou=grups ldap machine suffix = ou=maquines ldap idmap suffix = ou=usuaris # Volem que Samba ens sincronitzi el password # de Windows i de Unix ldap passwd sync = yes # No volem de cap manera que si eliminem un usuari ens esborri tota l'entrada # (podrÃem voler-lo deixar sense accés als sistemes Windows) ldap delete dn = noAra només falta indicar-li a Samba quina és la contrassenya del superusuari de LDAP i ja podem iniciar Samba. L'emmagatzemarà de forma segura en un fitxer secrets.tdb # smbpasswd -w passwordsupersecret # /etc/init.d/samba start Introduir una mà quina en el nostre dominiPer introduir una mà quina en el domini cal seguir un ritual molt especÃfic. Primer cal crear un compte UNIX de nom maquina$ on maquina és el nom de NetBIOS de la mà quina. Després cal bloquejar el compte i llavors des de Windows ja podrem entrar. Malauradament ens caldrà tenir l'usuari root al LDAP ja que en el moment d'afegir la mà quina al domini ens demanarà un usuari i contrassenya que per qüestions de Samba a UNIX tingui uid igual a zero, root normalment satisfà aquest requeriment. Noteu però que el compte que afegirem no serà pas de UNIX, només de Samba, per tant PAM no el podrà utilitzar per autenticar. # smbpasswd -a root New SMB password: Retype SMB password:Ara creem el compte de la mà quina. # useradd -c "Compte de la mà quina TESEU" -s /dev/null -d /dev/null teseu$ # passwd -l teseu$En aquest moment qualsevol podria fer-se passar per la mà quina TESEU i entrar al domini. Ara anem a la mà quina TESEU que té Windows entrant com Administrador. A l'opció Sistema del Panel de Control anem a la pà gina Identificación de Red i escollim entrar al domini (en el nostre cas SMBFERRER). Ara ens demanarà un usuari i password amb privilegis. Posem root i el password que hem usat al smbpasswd -a. Si tot va bé entrarem al domini i com de costum haurem de reiniciar la mà quina. En reiniciar podrem escollir Conectarse a: SMBFERRER. Ara ens falta l'usuari. Perquè un usuari pugui entrar ens cal que primer es trobi al LDAP com un usuari de UNIX. Després podem fer # smbpasswd -a usuari New SMB password: Retype SMB password:Noteu que li hem indicat a Samba que sincronitzi el password de Windows amb el de Linux per tant això ja hauria de configurar el password de Linux amb el mateix valor. ConsellsSi només teniu una mà quina amb Windows o no voleu que els perfils es desin remotament utilitzeu l'editor de polÃtiques de Windows (Inicio, Ejecutar, gpedit.msc) i canvieu la polÃtica Permitir sólo perfiles de usuario locales que es troba dins de Configuración del equipo, Plantillas administrativas, Sistema, Inicio de sesión. Són molt útils les eines de IDEALX que permeten gestionar els usuaris del LDAP i de Samba de forma còmoda. Més informació16:17
Aquest no és el primer document on s'explica com es pot unificar els logins en
una xarxa que conté Windows i Linux. Aquest article suposa uns coneixements
mitjans-alts d'administració de UNIX.Els actors de l'obra
En aquest drama hi intervenen per una banda un parell de sistemes Linux i un sistema Windows. Unificar logins estalvia feina, a casa meva només són tres mà quines però m'evita de tenir tres passwords que he de sincronitzar. Per resoldre aquest problema tenim el nostre amic LDAP. LDAP és una base de dades amb un model jerà rquic. Això vol dir que els elements s'identifiquen per la seva posició dins de l'arbre, enumerant els elements que hem anat creuant des de l'arrel fins al element. La bondat de LDAP és que permet emmagatzemar directoris : estructures organitzatives i informació que adquireix una forma jerà rquica. Una forma tÃpica de les organitzacions. L'inconvenient de LDAP és que hereta de diferents està ndards malignes com ara X.500 i abans d'entendre com funciona pot costar una mica. A més que la interacció amb el sistema LDAP és d'allò més primitiva (afortunadament hi ha alguna eina grà fica decent). La idea és emmagatzemar la informació dels usuaris i els grups al LDAP. Per integrar-ho tot utilitzarem per una banda nss_ldap que proporciona als programes la informació dels usuaris i grups que tenim al LDAP. Per altra banda ens caldrà dur a terme autenticació contra LDAP, per això disposem de pam_ldap. Als sistemes Windows no podem utilitzar NSS ni PAM. Afortunadament podem utilitzar Samba. La idea és que Samba desi i consulti al LDAP tot el que necessiti. En aquest punt la integració no és pas total ja que al LDAP podem tenir usuaris que no siguin usuaris de Windows. Tot i aixà Samba permet utilitzar el mateix nom d'usuari i sincronitzar la contrassenya tant de Unix com de Windows. Per tant si canviem el password de la forma correcta el canvi es veurà en els dos entorns. Per poder fer això caldrà configurar Samba perquè sigui el controlador primari de domini de la xarxa Windows NT. En aquest primer post ens concentrarem en unificar els sistemes UNIX. En el següent capÃtol ens concentrarem a acabar d'integrar els sistemes Windows. Arquitectura de la solucióEscollirem una mà quina Linux perquè executi el servidor de LDAP i l'instal·larem i el configurarem. Després tant en aquesta mà quina com en les altres mà quines Linux configurarem perquè obtinguin la informació d'usuaris i grups (NSS) per LDAP i autentiquin (PAM) també contra el LDAP. Preparació de LDAPLDAP és un protocol basat en TCP/IP per a l'accés de directoris de tipus X.500. Els directoris són estructures jerà rquiques on cada element de l'estructura emmagatzema una certa informació. Quina informació desa el node ve definida pel tipus de classe del node i per la pròpia classe. Cada node s'identifica pel camà que cal recórrer fins a arribar a ell. Aquesta estructura en arbre és molt convenient en organitzacions ja que és la que acaben adquirint a la prà ctica. És usual associar l'arrel del directori amb el domini de l'organització per exemple lamevaempresa.com. Estructura inicialEn el nostre cas hem utilitzat el nostre domini privat pigonet per construir la següent jerarquia.
Tal com s'ha indicat els nodes s'identifiquen pel seu recorregut des de l'arrel fins al node. Això s'anomena el dn (distinguished name). Fixeu-vos que la nostra jerarquia parteix del dc (domain component) pigonet. A sota hem afegit dos elements de tipus ou (organizational unit) que són usuaris i grups on desarem la informació dels usuaris i dels grups respectivament. Servidor de LDAP : OpenLDAP 2Ens caldrà una aplicació servidora de LDAP. Jo he escollit OpenLDAP perquè és lliure, però hi ha d'altres alternatives. És molt recomanable que utilitzeu la versió empaquetada de la vostra distribució aixà estalviareu problemes perquè l'heu compilada malament. El servidor de LDAP s'anomena slapd i es configura normalment a /etc/ldap/slapd.conf (la ubicació exacta pot variar entre distribucions). Mireu el manual de slapd per saber com es configuren els parà metres globals però assegureu-vos que permeteu binding anònim i que incloeu els schema's adequats. # Schema's que utilitzarem. Indiquen els tipus de formats que podrem utilitzar # als nodes. Els necessitarem per poder desar usuaris i grups. include /etc/ldap/schema/core.schema include /etc/ldap/schema/cosine.schema include /etc/ldap/schema/nis.schema include /etc/ldap/schema/inetorgperson.schema # Permetem binding anonim allow bind_anon_dnBinding consisteix en indicar a quin element de la jerarquia del LDAP ens connectarem, en funció de quina és, es pot configurar poder fer algunes operacions o d'altres, demanar password, etc. En el nostre cas per simplicitat permetrem bindings anònims, o sigui, que el client no indica a quin element de la jerarquia es connecta. En una instal·lació més segura aquesta opció seria inacceptable, evidentment. En la secció de bases de dades del fitxer slapd.conf hem configurat la següent jerarquia. # Format d'emmagatzematge de la BD database ldbm # El component arrel suffix "dc=pigonet" # L'element distingit que quan hom s'hi vinculi indicant la contrassenya # tindrà poders administratius rootdn "cn=admin,dc=pigonet" rootpw {SSHA}6JagzM6Hla8x3kiK64WK1w2TURSvVe5F # Directori dels fitxers fÃsicament directory "/var/lib/ldap" # Ã?ndexos que ens caldran per resoldre consultes de forma eficient index objectClass eq index cn,uid eq index uidNumber eq index gidNumber eq # Restringim l'accés a l'atribut del password # de l'usuari. # El pot modificar l'administrador # Es pot usar per autentificar # El seu propietari el pot modificar # La resta no pot accedir access to attribute=userPassword by dn="cn=admin,dc=pigonet" write by anonymous auth by self write by * none # L'administrador té accés a tot. # La resta només pot llegir access to * by dn="cn=admin,dc=pigonet" write by * readPer a més detalls sobre la configuració consulteu la bibliografia. Ens assegurem, amb el servidor apagat, que els Ãndexos estan correctament configurats. Per generar un password per a rootpw podem usar slappaswd. La ordre exacta per iniciar i finalitzar el servidor pot variar d'una distribució a una altra. # /etc/init.d/slapd stop # slappindex # /etc/init.d/slapd start Poblar la base de dadesAra que ja tenim el servidor LDAP presumiblement ben configurat ja podem afegir dades. Per fer-ho LDAP utilitza un format basat en text anomenat LDIF. Son conjunts de lÃnies on la primera columna fins als dos punts indica l'atribut de l'element que anem a introduir, començant sempre pel dn (Distinguished Name). Acte seguit introduirem com a minim l'atribut nou del dn i la resta d'atributs que calguin. Els següents LDIF permetran inicialitzar el nostre LDAP. $ cat arrel.ldif dn: dc=pigonet dc: pigonet objectClass: dcObject objectClass: organizationalUnit ou: Pigonet dn: ou=usuaris,dc=pigonet ou: usuaris objectClass: organizationalUnit dn: ou=grups,dc=pigonet ou: grups objectClass: organizationalUnitEl següent és un exemple de LDIF per a un usuari. $ cat usuari_nou.ldif dn: uid=carlos,ou=usuaris,dc=pigonet uid: carlos cn: Carlos Del Ojo Elias givenname: Carlos sn: Del Ojo Elias mail: carlos@rofi.pinchito.com objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: posixAccount objectClass: top objectClass: shadowAccount userPassword: {crypt}$1$77745874$yx3K7mB2L66JPS2fJPZHa0 shadowLastChange: 12473 shadowExpire: 12600 loginShell: /bin/bash uidNumber: 1002 gidNumber: 1011 homeDirectory: /home/carlos gecos: Carlos Del Ojo EliasFixeu-vos, el nou atribut del dn és uid=carlos i per tant ha d'acabar apareixent en la llista d'atributs. Fixeu-vos que el tipus de l'element (i per tant els atributs que pot tenir) són indicats en un atribut multivaluat que sempre hi és objectClass. Cal separar els diferents elements amb una lÃnia en blanc (un nou usuari aniria separat amb una linia en blanc). L'eina ldapadd permet afegir entrades en format LDIF al LDAP. $ ldapadd -W -x -f arrel.ldif -D cn=admin,dc=pigonet Password: (added new entry "dc=pigonet") (added new entry "ou=usuaris,dc=pigonet") (added new entry "ou=grups,dc=pigonet") $ ldapadd -W -x -f usuari_nou.ldif -D cn=admin,dc=pigonet Password: (added new entry "uid=carlos,ou=usuaris,dc=pigonet")Similarment amb els grups d'usuaris. dn: cn=src,ou=grups,dc=pigonet objectClass: posixGroup objectClass: top cn: src userPassword: {crypt}x gidNumber: 40 memberUid: bernat memberUid: carlosCom que afegir-ho a mà és un rotllo hi ha diferents eines que ens poden ajudar. Per una banda si volem migrar tot un /etc/passwd podem usar migrationtools. En el meu cas he hagut d'esmenar els scripts perquè no acabaven de rutllar bé. Si el que volem és afegir un usuari al LDAP podem usar algunes de les eines de IDEALX. Aquestes eines estan pensades per quan combinem LDAP amb SAMBA i potser ara mateix encara no ens serviran. Una eina grà fica per manipular LDAP és GQ que ens permetrà navegar pel nostre LDAP. Un cop tinguem els usuaris i grups al LDAP ja els podem eliminar de /etc/passwd i /etc/group. És evident que el root no el tindrem pas al LDAP i el deixarem a /etc/passwd. Preparant NSSName Switch Service ens permet configurar des d'on obtindrem la informació de les diferents bases de dades del sistema. En particular per al nostre cas ens interessen els usuaris, shadow i els grups. Això ho farem a cada mà quina on vulguem disposar dels usuaris de LDAP. Haurem d'instal·lar el paquet nss_ldap (libnss-ldap a Debian) i configurar el fitxer /etc/nsswitch.conf de la forma següent: passwd: files ldap group: files ldap shadow: files ldap # Aquà va la resta del fitxerAra ens manca configurar /etc/ldap.conf (/etc/libnss-ldap.conf a Debian). host 127.0.0.1 base dc=pigonet ldap_version 3 rootbinddn cn=admin,dc=pigonet nss_base_passwd ou=usuaris,dc=pigonet?one nss_base_shadow ou=usuaris,dc=pigonet?one nss_base_group ou=grups,dc=pigonet?oneLa contrassenya del superusuari la posarem a un fitxer /etc/ldap.secret en text clar i amb permisos 0600 només per a l'usari root. Ara podem comprovar que NSS està accedint correctament al servidor LDAP fent $ getent passwd ... carlos:x:1002:1011:Carlos Del Ojo Elias:/home/carlos:/bin/bash $ getent group src:x:40:bernat,carlos Preparant PAMCaldrà instal·lar el paquet pam_ldap (libpam-ldap a Debian). Aquest modul PAM treballa amb la configuració que hem definit abans a /etc/ldap.conf (o en el fitxer /etc/pam_ldap.conf a Debian). Això ho haurem de fer a cada mà quina que vulguem que s'autentifiqui contra LDAP. El truc està en permetre que l'autentificació per ldap sigui suficent en els mòduls auth i account. Per exemple si volem provar primer d'autenticar per LDAP i després provar sort amb els fitxers de UNIX podem configurar-ho aixÃ. Aquest és un exemple de /etc/pam.d/sshd. # AUTH auth required pam_nologin.so auth sufficient pam_ldap.so # És important que pam_unix.so utilitzi el primer password # sinó ens el demanaria un altre cop auth required pam_unix.so try_first_pass auth required pam_env.so # [1] # ACCOUNT account sufficient pam_ldap.so account required pam_unix.so # La resta del fitxer de configuració /etc/pam.d/sshdEn algunes distribucions com ara Gentoo s'utilitza el modul pam_stack.so que permet indicar un fitxer comú on fer la configuració de PAM. A Gentoo en particular aquest fitxer és /etc/pam.d/system-auth i el deixarem aixà # AUTH auth required /lib/security/pam_env.so auth sufficient /lib/security/pam_ldap.so auth sufficient /lib/security/pam_unix.so likeauth nullok try_first_pass auth required /lib/security/pam_deny.so # ACCOUNT account sufficient /lib/security/pam_ldap.so account required /lib/security/pam_unix.soEn aquest cas hi ha establert un mòdul pam_deny.so que sempre denega l'autenticació. De forma que és suficient que pam_ldap.so o pam_unix.so ens deixin entrar per no examinar aques últim. ConclusióComprenc que l'article deixa moltes aspectes per acabar de definir però dóna una idea de com s'hauria de configurar un Linux per treballar contra LDAP. Està clar que aquest és un tema d'administració lleugerament avançat però com a mÃnim s'intenta exposar les idees bà siques de com s'ha de dur a terme. En un proper article parlarem de com integrar SAMBA amb LDAP i per tant poder autenticar els usuaris amb el LDAP que hem instal·lat. Més informacióMay 4, 200508:17
En la gran majoria de cursos sobre administració de sistemes Unix (i GNU/Linux) es parla dels fitxers /etc/passwd
i /etc/shadow. Afortunadament hi ha vida més enllà d'aquest sistema.Gestió tradicional dels usuaris
La gestió tradicional dels usuaris a Unix ha passat pels fitxers de text /etc/passwd, /etc/shadow i /etc/group. En el primer llistem els usuaris, en el segon hi tenim la contrassenya encriptada (és un fitxer de lectura restringida) i en el tercer els grups del sistema i els membres que hi pertanyen. PAMDurant molt de temps amb això n'hi ha hagut prou per a la gran majoria de situacions. De fet avui dia encara s'utilitza per a Unix en mà quines personals perquè fa bé la seva funció. Malauradament amb la proliferació de les xarxes locals i l'administració centralitzada aquest sistema no s'adapta gens bé. És per aquest motiu que Sun, i després fou adaptat a GNU/Linux, va crear el que s'anomena PAM (Pluggable Authentication Modules). Els mòduls d'autentificació són un conjunt de llibreries dinà miques (.so) que es responsabilitzen de l'autenticació. Les aplicacions només han de sol·licitar via la llibreria de PAM que es dugui a terme l'autentificació. Cada aplicació pot tenir una configuració especÃfica. Per exemple, el programa login ens deixa entrar al sistema per un terminal. Les versions antigues es cuinaven elles l'autenticació consultant els fitxers abans esmentats. Ara, però, ho deleguen a libpam. L'autenticació dependrà de com estiguin configurat el programa. Directori /etc/pam.dLa forma original desenvolupada per Sun consistia en configurar les aplicacions en un fitxer /etc/pam.conf. L'única pega d'aquest sistema és que el fitxer acaba quedant molt gran si hom hi té molts clients de PAM. A GNU/Linux cada aplicació es configura en un fitxer individual dins del directori /etc/pam.d. Anem a mirar per exemple la configuració de PAM de login de Debian Woody 3.0 (les distribucions més modernes també porten PAM però el configuren perquè sigui molt més flexible i ens molestaria per l'explicació). El fitxer en qüestió és /etc/pam.d/login. auth requisite pam_securetty.so auth requisite pam_nologin.so auth required pam_env.so auth required pam_unix.so nullok account required pam_unix.so session required pam_unix.so session optional pam_lastlog.so session optional pam_motd.so session optional pam_mail.so standard noenv password required pam_unix.so nullok obscure min=4 max=8 md5La primera columna indica el tipus de mòdul. Hi ha quatre tipus de mòduls i no tots ells tenen sentit en totes les situacions.
Els mòduls es van examinant seqüencialment quan accedim a un servei. Primer els auth, després els account, els session. Els mòduls poden impedir que puguem accedir al servei en funció del seu grau de requeriment.
Cal a dir que aquests graus de requeriment es poden afinar millor però per a la majoria de situacions en tindrem prou. Ara analitzem la configuració del fitxer /etc/pam.d/login. auth requisite pam_securetty.so auth requisite pam_nologin.so auth required pam_env.so auth required pam_unix.so nullokEl mòdul pam_securetty.so ve per defecte amb Linux-PAM i permet configurar a través del fitxer /etc/securetty des de quins terminals pot fer login l'usuari root. És tÃpic no permetre que l'usuari entri al sistema si no és per un dels terminals de text (o sigui davant del monitor i el teclat). El mòdul pam_nologin.so també ve amb Linux-PAM i impedeix que els usuaris facin login si existeix el fitxer /etc/nologin i només permet que entri root. El mòdul pam_env.so permet establir variables d'entorn en la fase de login. A priori sembla que hagi de ser quelcom per fer a account però les variables d'entorn s'assignen a la fase d'establiment de credencials. Finalment el mòdul pam_unix.so fa l'autentificació contra els fitxers /etc/passwd i /etc/shadow. Alhora que llegeix de /etc/group els grups de l'usuari. El parà metre nullok permet que puguin entrar usuaris amb un password en blanc (per defecte no ho permet). account required pam_unix.soAquà es realitza la gestió del compte considerant la data de caducitat i d'altres parà metres sobre el password que apareixen a /etc/shadow (data de l'últim canvi, etc). session required pam_unix.so session optional pam_lastlog.so session optional pam_motd.so session optional pam_mail.so standard noenvAquà el mòdul pam_unix.so és afegir una entrada a syslog indicant que l'usuari ha fet login, també s'apuntarà quan faci logout. Els mòduls pam_lastlog.so i pam_motd.so mostren a l'usuari l'últim cop que va fer login i el message of the day (normalment /etc/motd). Finalment pam_mail.so ens indica si tenim correu electrònic nou al compte. Tots aquests missatges apareixen just abans d'obtenir el shell que login iniciarà . Més enllÃLa grà cia d'aquest sistema és que podem delegar l'autenticació als mòduls. Per exemple podem tenir tot un sistema unificat de logins a través de LDAP amb pam_ldap o a través d'un domini Windows NT utilitzant winbind i pam_winbind. NSSFixeu-vos que ara només hem considerat l'autenticació. Però els sistemes Unix tenen diferents bases de dades que també voldrem delegar. Una d'elles és, com no, /etc/passwd. Si fem autenticació contra un LDAP, contra un NIS o contra un domini Windows NT està clar que la llista d'usuaris i grups no pot sortir de /etc/passwd. Per resoldre aquest problema Sun va inventar NSS (Name Service Switch). La llibreria GNU/Libc incorpora un mecanisme molt similar (que no igual) que permet a través del fitxer /etc/nsswitch.conf configurar d'on obtindrem la informació de les diferents bases de dades del sistema (usuaris, grups, à lies de correus, protocols, hosts, etc). Més informacióApril 29, 200503:17
Entre ahir i avui he renovat parcialment el parc informà tic de casa meva.
Per una banda hem de dir adéu a un ordinador Pentium II 233 MHz que ha donat molt bon servei aquest temps. De tu només ens queda el record d'haver estat el meu primer ordinador i la seva CPU. Has estat un bon ordinador caecus.
D'altra banda donar la benvinguda a odisseu, penelope i tiresies. odisseu és una nova mà quina AMD64 3200+ que utilitzaré jo personalment. penelope és el meu antic Athlon XP 1800+ (abans anomenat ordenata2) i que ara l'utilitza la meva famÃlia. Finalment tiresies, un Pentium III 800 antic ordinador familia i que ara fa de servidor de la xarxa. Potser us fa curiositat saber el motiu dels noms. Tirèsies va ser condemant per Atenea a quedar cec després que aquest la sorprengués banyant-se. A canvi Atenea li va concedir el do de la profecia. (Hi ha altres històries sobre el motiu de la ceguesa de Tirèsies). Penèlope era la dona d'Odisseu, rei d'Ã?taca i fill de Laertes. Finalitzada la guerra de Troia, Odisseu havia de tornar a casa. Tothom donava per mort a Odisseu menys Penèlope qui enganyava i s'inventava argúcies per mantenir apartats els pretendents d'Ã?taca. April 23, 200522:17
No tots els programes que farem seran amb interfÃcie grà fica i alguns d'ells
són de lÃnia d'ordres. La interacció sovint amb aquest tipus d'aplicacio es fa
mitjançant parà metres.
Les aplicacions en la gran majoria de sistemes arrenquen en una rutina main que té la capçalera següent. int main(int argc, char* argv[]);on argc indica el número d'arguments que ha rebut el programa (com a mÃnim un) i argv conté tots els arguments de 0 a argc-1. D'aquesta forma les següents invocacions suposaran els següents valors: Invocació argc argv[0] argv[1] argv[2] ls -lh 2 ls -lh /usr/bin/ls -l -h 3 /usr/bin/ls -l -h ls --color -l 3 ls --color -lCom es dedueix rà pidament analitzar aquests parà metres és feina innecessà ria però que cal fer cada cop. Aquest problema sorgeix sovint en la gran majoria d'aplicacions de lÃnia d'ordre i és per això que existeixen ja solucions per tractar els parà metres d'un programa. Aquà parlarem de dos opcions que tenim disponibles a GNU/Linux, getopt i getopt_long, però existeixen altres opcions que trobareu al final. getoptL'opció de getopt és de les més senzilles però alhora més portables si hem de portar una aplicació fora de GNU/Linux. Bà sicament tot gira al voltant de la rutina del mateix nom, getopt on li indicarem quina mena de parà metres ens esperem. Suposem que estem fent una aplicació i volem tres parà metres. Per una banda -o on especificarem un fitxer de sortida. També voldrem un parà metre -d per activar opcions de depuració i finalment la tÃpica opció -h per mostrar l'ajuda. La rutina getopt rep tres parà metres que són argc, argv i una cadena d'opcions que volem que reconegui. getopt només reconeix opcions d'un sol carà cter (-h però no --help). Cada opció pot anar seguida d'un valor (de la forma -ofitxer.txt o bé -o fitxer.txt). La rutina getopt ens anirà tornant quina opció ha reconegut. En el nostre cas la cadena d'opcions a indicar és "o:hd". Els dos punts de o són per indicar que -o porta un valor associat. Com a extensió de GNU, les opcions poden anar seguides de :: per indicar que el parà metre es optatiu (una cosa de l'estil -z, -z9 es podria indicar com "z::"). #include #include #include int main(int argc, char* argv[]) { char depuracio = 0, ajuda = 0, error = 0; char* fitxer_sortida = NULL; char param; while ( (param = getopt(argc, argv, "o:hd")) != (char)(-1) ) { switch(param) { case 'h' : ajuda = 1; break; case 'o' : // La variable "optarg" té l'argument fitxer_sortida = strdup(optarg); break; case 'd' : depuracio = 1; break; case '?': // Aquest és el valor quan getopt no enten una opció. // Noteu que getopt ja haurà escrit un missatge d'error, // no cal que ho fem nosaltres. error = 1; } } if (error) { // Aquà mostrarÃem l'ajuda mostrar_ajuda(); return (EXIT_FAILURE); } if (ajuda) { mostrar_ajuda(); return (EXIT_SUCCESS); } /* Hi ha parà metres que no són opcions */ if (optind < argc) { int index; for (index = optind; index < argc; index++) { tractar_parametre(argv[index]); } } } Opcions llargues a l'estil GNULa interfÃcie getopt és senzilla d'utilitzar però sovint disposar d'opcions amb noms més descriptius que un sol carà cter és d'agraïr. En aquest sentit i com a extensió de GNU/Libc disposem de getopt_long, el seu ús és relativament més complex. Per cada parà metre cal inicialitzar una structura struct option on els diferents camps són el nom de l'argument, quin tipus d'argument és, una variable on podem escriure i un valor que utilitzarem quan ens trobem l'opció. getopt_long es comporta igual que getopt quan troba una opció d'una sola lletra i utilitza una llista de struct option per saber què ha de fer amb una opció llarga. #include #include #include #include int main(int argc, char* argv[]) { // Els fem int perquè és el que utilitza getopt_long int depuracio = 0, ajuda = 0, error = 0; struct option opcions_llargues[] = { // Quan trobem --debug llavors depuracio=1 {"debug", no_argument, &depuracio, 1}, // Quan trobem --nodebug llavors depuracio=0 {"nodebug", no_argument, &depuracio, 0}, // Quan trobi --output retornarà 'o' {"output", required_argument, NULL, 'o'}, // Quan trobi --output retornarà 'h' {"help", no_argument, NULL, 'h'}, // Cal acabar l'estructura amb NULLs {NULL, NULL, NULL, NULL} }; int index_opcions; char* fitxer_sortida = NULL; char param; while ( (param = getopt_long(argc, argv, "o:hd", opcions_llargues, &index_opcions)) != (char)(-1) ) { switch(param) { case 'h' : ajuda = 1; break; case 'o' : // La variable "optarg" té l'argument fitxer_sortida = strdup(optarg); break; case 'd' : depuracio = 1; break; case '?': // Aquest és el valor quan getopt no enten una opció. // Noteu que getopt ja haurà escrit un missatge d'error, // no cal que ho fem nosaltres. error = 1; } } if (error) { // Aquà mostrarÃem l'ajuda mostrar_ajuda(); return (EXIT_FAILURE); } if (ajuda) { mostrar_ajuda(); return (EXIT_SUCCESS); } /* Hi ha parà metres que no són opcions */ if (optind < argc) { int index; for (index = optind; index < argc; index++) { tractar_parametre(argv[index]); } } } Més informació
March 23, 200507:55
Sovint ens toca actualitzar software perquè tenen fallades de seguretat que explotades amb èxit podrien tenir efectes devastadors
en els nostres sistemes. Un error de programació clà ssic que introdueix aquestes vulnerabilitats és l'anomenat buffer overflow.C i char*
Per tots és sabut que el llenguatge C no té un tipus de cadena especÃfic com sà tenen molts llenguatges de programació. Per conseguir un efecte similar disposem de char* que no és més que un array de carà cters. Per saber on acaba la cadena s'utilitza un carà cter NUL (amb valor zero). Les cadenes de C, char*, no tenen cap forma d'indicar la longitud sinó que s'ha de saber per on ens trobem el carà cter NUL. El problema succeeix quan aquest carà cter zero no apareix: les rutines de manipulació de cadenes de C seguiran considerant la resta de dades com a part de la cadena. Això fa que es puguin explotar per modificar zones de memòria difÃcilment accessibles des de la interfÃcie del programa. Exemple senzillAnem a veure un exemple senzill de buffer overflow en el següent codi. void funcioVictima(char* c) { // El compilador l'alinearà a 24 char buff[10]; strcpy(buff, c); }Aquesta funció fa ús de la funció de la llibreria està ndard de C strcpy. El que fa és copiar una cadena a l'adreça que li indiquem. En aquest cas hem reservat està ticament 10 carà cters a la pila (variable buff). La pregunta que tothom s'està fent ara és què passa si la cadena que li arriba pel parà metre c és de més de 10 carà cters? Bà sicament el que passarà és que ens carregarem la pila. I llavors podrÃem controlar-la al nostre antuvi. Per exemple podem utilitzar aquest error de programació per executar una funció que no crida ningú. void noEmCrideu(void) { printf("Qui m'ha cridat? "); } void funcioVictima(char* c) { // El compilador GCC l'alinearà a 24 char buff[10]; strcpy(buff, c); } int main(int argc, char* argv[]) { unsigned int* overflow = (int*)malloc(20*sizeof(int)); unsigned char* overflow_char = (char*) overflow; // Omplim els 24 primers carà cters // aixo son els 6 primers "int" int i; for (i = 0; i < 24; i++) { overflow_char[i] = '.'; } // Copiem el EBP vell a la pila // Només es pot fer amb assembler __asm__ ( "mov %%ebp, %0" : "=m" (overflow[6]) : ); // L'adreça de retorn de la rutina overflow[7] = (unsigned int)noEmCrideu; // L'adreça de retorn de "noEmCrideu" overflow[8] = (unsigned int) &&etiqueta; // Overflowegem la pila funcioVictima(overflow_char); // Si tot ha anat bé haurÃem d'estar aquà etiqueta: printf ("Aquà no ha passat res :P "); return 0; }Bà sicament això passa perquè el bloc d'activació de la funcioVictima és el següent: AdreçaContingutValor del buffer overflowNotes EBP-24 Adreça del vector buf strcpy copiarà el buffer. Per tant aquà correspon amb *((char*)overflow) El compilador l'ha posat aqui per eficiència. ... ... ... EBP+0 El contingut del EBP anterior a aquest bloc d'activació Això és overflow[6]. Aquesta adreça la posem a mà amb assembler. Usarem el valor de main aixà a noEmCrideu li semblarà que l'haguem cridat des de main. EBP+4 L'adreça de retorn de funcioVictima Això és overflow[7]. Aquà posarem l'adreça de noEmCrideu EBP+8 L'adreça de retorn de noEmCrideu Això és overflow[8]. Aquà posarem l'adreça de etiqueta per tornar al main correctament.Si compilem i executem aquest programa ens donarà el resultat següent: $ gcc -g -o prova_salt prova_salt.c $ ./prova_salt Qui m'ha cridat? Aquà no ha passat res :PHem estat capaços de modificar correctament la pila. Això ens ha permès saltar a una funció que no crida ningú i després tornar al main. Un altre exempleAra suposem que la cadena que li passem a la rutina fa un salt a la pròpia cadena i aquesta conté codi mà quina. Malauradament el nivell de protecció d'execució a IA32 és a nivell de segment i no de pà gina. Per tant les pà gines de pila i del heap normalment són executables. Simplement el que fem és desapilar el parà metre que ha rebut funcioVictima i posar un 3 a eax de forma que el resultat del nostre programa sigui 3. Noteu que les noves arquitectures compatibles amb IA32 com ara AMD64 i IA32-EMT64 incorporen protecció d'execució a nivell de pà gina. És l'anomenat NX (Not Executable) i l'estan comercialitzant com a "protecció antivirus". Per tant en aquests sistemes on el sistema operatiu impedeixi l'execució de pà gines de la pila i el heap aquest exemple no funcionarà . int main(int argc, char* argv[]) { unsigned int* overflow = (int*)malloc(20*sizeof(int)); unsigned char* overflow_char = (char*) overflow; // Omplim els 24 primers carà cters // aixo son els 6 primers "int" int i; for (i = 0; i < 24; i++) { overflow_char[i] = '.'; } // Copiem el EBP vell a la pila // Només es pot fer amb assembler __asm__ ( "mov %%ebp, %0" : "=m" (overflow[6]) : ); // L'adreça de retorn de la rutina overflow[7] = (unsigned int)&overflow[8]; /* Codi mà quina de IA32 0: 83 c4 04 add $0x4,%esp 3: b8 03 00 00 00 mov $0x3,%eax 8: c9 leave 9: c3 ret IA32 és una arquitectura little endian. Ens cal donar la volta als enters de 32 bit. 83 c4 04 b8 -> b8 04 c4 83 03 00 00 00 -> 00 00 00 03 c9 c3 -> 90 90 c3 c9 (90 es el codi del "nop", podÃem haver posat qualsevol cosa) */ overflow[8] = 0xb804c483; overflow[9] = 0x00000003; overflow[10] = 0x9090c3c9; // Overflowegem la pila funcioVictima(overflow_char); // Si tot ha anat bé haurÃem d'estar aquà etiqueta: printf ("Aquà no ha passat res :P "); return 0; }Efectivament el resultat del programa acaba sent 3. $ gcc -g -o prova_codi prova_codi.c $ ./prova_codi ; echo $? 3 Com evitar-losEls buffer overflows s'han d'evitar sempre que sigui possible. Per una banda ja hem vist que algunes funcions de C no hi ajuden. Per tant és important utilitzar les versions segures. Per a l'exemple que hem utilitzat tenim la funció strcpy. L'equivalent segura és strncpy on s'especifica el número de carà cters a copiar (noteu que a l'exemple li podem passar 10 però en el cas que s'hagin copiat 10 carà cters caldrà triturar amb NUL el carà cter buff[9]). Malauradament això suposa reescriure molt de codi i sovint no és possible fer-ho. Una altra solució és establir mecanismes de protecció. Aquests mecanismes de protecció de la pila afegeixen un canari aleatori a la pila. Si el valor d'aquest canari ha canviat llavors vol dir que algú s'ha passejat per la pila. Cal dir que aquesta comprovació s'ha de fer sempre just abans de sortir d'una funció i per tant que causa un impacte en les aplicacions. Hi ha diferents mecanismes de protegir-nos. Un de prou extès ja que el porta la distribució Gentoo per defecte és ssp de IBM. Però hi ha altres implementacions com ara StackGuard de Immunix. El nostre gcc porta ssp i l'hem posat a prova. $ gcc -fstack-protector-all -o prova_salt prova_salt.c $ ./prova_salt prova_salt: stack smashing attack in function funcioVictima() Avortat $ gcc -g -fstack-protector-all -o prova_codi prova_codi.c $ ./prova_codi prova_codi: stack smashing attack in function funcioVictima() AvortatEl problema en realitat no s'ha resolt però ara hem conseguit passar d'una vulnerabilitat seriosa que podria implicar execució (possiblement remota) de codi a una simple denegació de servei. El programa aborta en detectar una corrupció de la pila. La solució definitiva, és però, ser molt curós a l'hora d'escriure codi que manipuli cadenes. Més informació07:55
Per allà el 1992, quan Borland va treure la seva setena (i última) versió de
Turbo Pascal per a DOS a la caixa del producte hi mencionava una dada que avui
dia és difÃcil de trobar en les eines de desenvolupament. Turbo Pascal 7 era
capaç de compilar 85.000 lÃnies de codi per minut en un Compaq Deskpro 386/33.
El motiu de tan insòlita publicitat era deguda a una de les deficiències principals del llenguatge C/C++ i que no patia Turbo Pascal. En el llenguatge C/C++, cada cop que es compila un fitxer cal carregar totes les capçaleres a les que es refereix. Això en Turbo Pascal no passa ja que les unitats d'un programa (un fitxer de codi podia contenir un program pròpiament dit o una unit que implementava el concepte de mòdul) es compilaven en un format intermedi binari (amb extensió TPU). Quan el compilador compilava un program o una unit que referÃs a d'altres unit consultava l'existencia de la versió compilada. Si no la trobava compilava la unit referida. Si la trobava es limitava a consultar els sÃmbols (variables i funcions) que definia en un Ãndex que contenia el fitxer binari. Aquà és on raïa el secret de la velocitat de Turbo Pascal: no haver de recompilar cada cop. En aquella època Turbo Pascal era un seriós competidor del llenguatge C/C++ en quant a velocitat. La gent no li importava programar en un llenguatge o altre perquè la interoperabilitat no era tan crucial a DOS. Però carai, era difÃcil compilar 85.000 lÃnies de codi en un minut (més de 1400 lÃnies per segon) quan usaves C/C++ ja que cada fitxer podia suposar haver-ne d'incorporar moltes. Precompilació de capçaleresEvidentment haver de llegir cada cop els fitxers de capçalera per compilar és una operació inútilment costosa. És per aquest motiu que els fabricants de compiladors de C/C++ van decidir donar una solució acceptable : precompilar les capçaleres. La tècnica consisteix en fer el mateix que feia Turbo Pascal, precompilar les capçaleres i desar-les en un format binari eficient. D'aquesta manera quan es compila un fitxer només cal fer una consulta a l'Ãndex del precompilat i no cal compilar-lo de nou. Els compiladors comercials més coneguts (Visual C++, Borland C++, Intel C++) disposen de suport a les capçaleres precompilades. El compilador de GNU GCC no ha disposat d'aquesta caracterÃstica fins a la recent versió 3.4. Per fer-ho simplement cal compilar la capçalera com un fitxer normal. Per al nostre exemple usarem la llibreria gtkmm, un wrapper en C++ de la llibreria GTK+. Suposem el fitxer header.h següent: #ifndef HEADER_H #define HEADER_H #include // Un include de conveniència que inclou tota la llibreria #endifAnem a calcular quant ocupen totes les capçaleres de la llibreria. $ g++ -E `pkg-config --cflags gtkmm-2.0` header.h > mida_headers $ ls -lh mida_headers -rw-r--r-- 1 roger users 2,1M 10 oct 22:08 mida_headerscom podeu observar haver de compilar més de 2 megabytes de codi cada cop és bastant costós. Anem a precompilar les capçaleres. $ g++ -c `pkg-config --cflags gtkmm-2.0` header.h $ ls -l header.h.gch -rw-r--r-- 1 roger users 33M 10 oct 22:11 header.h.gchAixò genera un fitxer header.h.gch que ocupa força espai. És el preu que haurem de pagar per la velocitat. En el meu sistema ocupa 33 Mb (!!). Sigui ara un fitxer header.c que inclogui header.h. Anem a comparar la velocitat de compilar usant un header precompilat a no usar-lo. $ time g++ `pkg-config --cflags gtkmm-2.0` -c header.c real 0m0.227s user 0m0.140s sys 0m0.047s $ rm header.h.gch $ time g++ `pkg-config --cflags gtkmm-2.0` -c header.c real 0m3.183s user 0m2.868s sys 0m0.225sCom podeu observar la diferència és molt significativa. El suport de capçaleres precompilades a GCC 3.4 és encara força simple i subjecte a restriccions relativament estrictes. A més se sap que pot provocar que el compilador es pengi. En qualsevol cas és un primer pas per situar-se a un nivell similar a la resta de compiladors. És d'esperar que en la nova sèrie GCC 4.x el suport de capçaleres precompilades millori. Més informació
07:55
Un problema freqüent que se solen trobar els programadors quan implementen una
aplicació és la de resoldre els problemes de memòria dinà mica. Sempre és font
de problemes i maldecaps. Malauradament afecta a quasi tots els entorns de
desenvolupament però sol ser especialment greu en llenguatges com C i C++.Problemes de memòria
La gran majoria de llenguatges de programació es veuen afectats pels possibles errors de programació en l'aspecte de memòria dinà mica. D'errors de memòria dinà mica en trobem molts i variats però tots es podrien classificar en algun dels dos casos següents:
Quant a les fugues de memòria no sempre és necessari resoldre-les. Si el sistema operatiu garanteix que s'alliberen els recursos sol·licitats en finalitzar l'aplicació i la quantitat de memòria que malgastem no augmenta en funció de la duració de l'execució del programa llavors no és imprescindible esmenar-ho. De fet aquesta estatègia l'utilitzen moltes llibreries que sol·liciten memòria per a buffers interns que seran usats durant l'execució (i aixà estalviar sol·licitar i lliberar memòria contÃnuament). L'eina ValgrindEl propòsit de l'article, però, era parlar d'aquesta eina tan magnÃfica com és Valgrind. Valgrind és una eina pensada per a l'arquitectura IA32 que permet executar l'aplicació que estem desenvolupant a la cerca de problemes de memòria. En realitat Valgrind porta més opcions com un analitzador de la quantitat de memoria dinà mica gastada o un analitzador del rendiment de la cache. Per il·lustrar-ho he escollit un error clà ssic quan es programa amb C++. Tot i que aparentment el codi sembla perfectament correcte conté un memory leak potencial. No intenteu trobar-li massa sentit al programa, bà sicament Numero i Parell guarden un punter a un enter, només que Parell utilitza el valor de Numero per construir el doble del valor usat per construir-la. 07:55
Sovint ens trobem amb problemes quan una aplicació vol produir un so. Resulta
que algú altre ja està ocupant el dispositiu de so. Anem a veure una manera de
resoldre-ho.El so a Linux
El subsistema de so tradicional disponible a tots els UNIX és l'anomenat Open Sound System o simplement OSS. Aquest subsistema de so està disponible a la gran majoria de *nix: Linux, BSD, Solaris, AIX, etc. Quan es va dissenyar OSS cobria bona part de les necessitats de so que hi havia per aquell moment. Però al llarg del temps en l'entorn Linux s'ha impulsat una alternativa a OSS. Aquesta alternativa ve motivada per algunes limitacions del sistema OSS i per altra banda la manca de drivers lliures. En aquest sentit cal dir que l'empresa 4Front ofereix comercialment drivers OSS per a diferents UNIX inclòs Linux. Aquesta alternativa s'anomena Advanced Linux Sound Architecture, ALSA, i ve a proporcionar una arquitectura amb majors possibilitats que OSS. ALSA proporciona els drivers de les targetes de so, que es troben de sèrie al kernel 2.6 de linux, i una llibreria de programació de forma que les aplicacions poden usar ALSA nativament. A més ALSA porta una capa de compatibilitat amb OSS de forma que les aplicacions fetes per a OSS poden seguir funcionant amb els drivers d'ALSA. El repte de l'escriptori multimèdiaDeixant de banda si GNU/Linux està preparat per a l'escriptori, és clar que en aquests últims anys s'ha incrementat l'activitat centrada en el desenvolupament d'escriptoris per a GNU/Linux. En aquest sentit s'ha observat que tant ALSA com OSS no proporcionen, almenys de forma directa, mecanismes perquè les diferents aplicacions puguin emetre sons alhora. La majoria de targetes de so porten un o dos processadors de so que no pot fer mescla (algunes noves targetes permeten la mescla per hardware) de forma que quan una aplicació ha obert el dispositiu de so cap altra pot utilitzar-lo. Això fa que només pugui estar "sonant" una aplicació alhora. Hi ha diferents formes de resoldre aquest problema però cap ens proporcionarà una solució total (a menys que usem targetes amb mescla hardware). Una d'elles consisteix en utilitzar servidors de so on les aplicacions de l'escriptori enviaran el so. El servidor mesclarà el so i l'enviarà adequadament a la targeta de so. Exemple d'aquestes solucions son Enlightenment Sound Daemon (ESD) i KDE/aRTs. Malauradament aquesta solució sol imposar massa latència i la sensació que es percep és que tot va molt feixuc. Cal a dir que aquest mecanisme obliga a escriure les aplicacions expressament perquè utilitzin aquests servidors. Una altra solució és usar el mecanisme de plugins d'ALSA. Un d'aquests plugins s'anomena dmix i permet que diverses aplicacions ALSA puguin reproduir so alhora. Un altre plugin és el de JACK. JACK és un servidor de so però dissenyat per a tenir baixa latència i pensat perquè diferents aplicacions s'intercanviïn el so. Configurar dmixPer configurar dmix crearem un fitxer .asoundrc al nostre HOME. Per començar podem provar amb la configuració següent: pcm.!default { type plug slave.pcm "dmix" }el que està dient és que es redirigeixi el dispositiu de so per defecte a dmix. Aquest és el dispositiu que obren les aplicacions si no se'ls ha indicat explÃcitament que n'obrin un altre. Automà ticament serà redirigit a dmix qui farà la mescla pertinent. Per provar que funciona necessitem l'eina aplay del paquet alsa-utils i un fitxer WAV que duri uns segons. $ (aplay fitxer.wav &); aplay fitxer.wavSi tot ha anat bé s'executaran dos aplay en paral·lel i sentirem dos cops fitxer.wav amb una petita separació en el temps entre els dos. Configuració més sofisticadaJa s'ha comentat que hi ha targetes amb mesclador per hardware (com la SoundBlaster Live!) o targetes amb més d'un processador de so (com la SoundBlaster 128 PCI). En aquest últim cas pot ser molt útil redirigir tot el so de les aplicacions ALSA al segon processador de so i deixar el primer lliure. AixÃ, si hem d'executar una aplicació OSS aquesta obrirà per defecte el primer processador de so (noteu que una segona aplicació OSS alhora ja no funcionaria). En aquest cas la configuració és una mica més complexa: pcm.!default { type plug slave.pcm "ossmix" } pcm.ossmix { type dmix ipc_key 1099 # Ha de ser un valor únic slave { pcm "hw:0,1" # hw:0,1 és el segon processador # hw:0,0 seria el primer } bindings { 0 0 1 1 } } "ALSAitzant" aplicacions OSSEl paquet alsa-utils porta un script, aoss, que permet executar aplicacions OSS de forma que acabin utilitzant ALSA. Per fer-ho s'aprofita de la llibreria libaoss que intercepta els accessos al dispositiu de so OSS i els redirigeix a ALSA. No funciona pas amb totes les aplicacions però si amb la gran majoria. Ens caldrà afegir la següent entrada al nostre fitxer .asoundrc. pcm.dsp0 { type plug slave.pcm "ossmix" }Ara ja podem usar aoss per a l'aplicació: $ aoss aplicacio_que_nomes_usa_oss Més informació07:55
Tot i que no fa massa temps que el tinc, he instal·lat GNU/Linux a
hydra. Afortunadament sembla que la branca PPC32 del kernel Linux disposa de la gran majoria de coses que
necessitarem.
Abans de començar si desitgem tenir arrencada dual Mac OS X i Linux haurem de particionar el disc en dos trossos. El primer l'haurem de marcar com a espai lliure i el segon partició HFS+ de Apple. Això es pot fer des del gestor de disc de l'instal·lador de Mac OS X. La instal·lació de Mac OS X s'haurà de fer sobre la segona partició. No sobre la primera. Aixà quan més endavant creem les particions de Linux una d'elles haurà de ser bootstrap i com que serà la primera és la que arrencarà OpenFirmware (una espècie de BIOS dels PowerPC). La distribució que he escollit és Gentoo. El motiu és ben simple, la coneixo raonablement. La instal·lació està prou ben documentada. A més em permetia aprofitar el codi font que ja tinc descarregat en un altre ordinador amb Gentoo, via NFS, aixà que almenys puc estalviar temps de descà rrega, que és l'únic que es pot estalviar ja que caldrà invertir molt de temps compilant (un G4 a 1.06 GHz no és precisament una fletxa ;) Sembla que la branca PPC de Gentoo està una mica antiquada i això em va suposar haver d'actualitzar molts paquets. Vaig decidir utilitzar la branca inestable ~ppc de Gentoo perquè pel que volia m'anava millor. La instal·lació no va estar exempta de problemes. Cal instal·lar explÃcitament els headers de la branca 2.6 del kernel, compilar GNU GCC 3.4 abans que GNU Libc (perquè el GCC 3.2 que ve amb el livecd li falten opcions GNU Libc 2.3 els demana) i corregir un include del kernel perquè mancava una macro i no compilava el paquet kbd. Aquest últim fenomen també afecta al paquet mac-fdisk que simplement no compila i el codi sembla ser força antiquat, em vaig limitar copiar el binari del livecd. Quant al kernel, val la pena saber que porta algunes opcions menys que el seu equivalent de IA32, cosa que facilita trobar els drivers i les opcions apropiades per a els Apple. En particular hi ha diverses opcions per a iBook i PowerBook. Són interessants les que tracten del control d'energia: escalat de freqüència de la CPU (útil per reduir la velocitat de la CPU quan la cà rrega és baixa), control dels ventiladors i els sensors, i emulació APM per consultar la bateria. Cal tenir una versió superior a 2.6.7-bk16 perquè tot funcioni en el meu iBook (he posat la versió 2.6.8.1). Tot i això no podrem gaudir de tots els dispositius. La ATI Radeon 9200 no porta acceleració nativa 3D, hom confia que algun dia hi haurà drivers no només per a IA32. Tampoc podrem gaudir del modem USB intern, ja que és un dispositiu Conexant i sembla que els drivers per a Linux no el detecten correctament (potser és un problema amb la branca 2.6). En definitiva, tot i els petits entrebancs que m'he anat trobant, tinc la sensació d'estar al teu Linux de sempre encara que sigui en una arquitectura totalment diferent com és la PowerPC. Més informació
07:55
Recentment he adquirit un iBook. En particular el model de 12" on només li he afegit 256 MB de RAM més, em semblava que només 256 MB era ben poc pels temps que corren. L'he batejat amb el nom hydra en referència al sistema Aqua.
Els meus interessos com a estudiant d'enginyeria informà tica són força particulars. Tot i que no era directament una necessitat imperiosa tenir un ordinador portà til sà que havia sospirat sovint per algun ordinador que no fos de l'arquitectura IA32, independentment que fos portà til o no. Perquè? Per què massa temps amb una mateixa cosa acaba fent tuf. A més crec que val la pena tenir d'altres perspectives en quant a computadores, ni que sigui esbiaixadament amb ordinadors projectats per al mercat domèstic. Malauradament qualsevol cosa que no sigui tipus PC és massa car per a una pretensió domèstica. Arquitectures alternatives com ara Sun SPARC o SGI són massa cares per a un interès particular com el meu. Algun cop havia estat a punt d'adquirir algun equipament de segona mà , però sempre m'havia fet enrere.
Apple va decidir crear un sistema operatiu basat en UNIX BSD (fet que li confereix major interoperabilitat i portabilitat que mai) anomenat Mac OS X. Mac OS X no seria un altre UNIX més si no fos que va potenciat per una interfÃcie grà fica molt espectacular i per un entorn d'escriptori realment integrat. En comparació amb les versions anteriors, Mac OS X ha despertat un major interès ja que és relativament més fà cil portar aplicacions a Mac, encara que no facin ús de totes les caracterÃstiques avançades de la interfÃcie. A més, l'arquitectura que utilitza Apple no és IA32 sinó PowerPC, una arquitectura RISC i per tant força diferent de la que ens trobem a un PC convencional. Això li confereix un interès especial per part meva. Com a portà til i de cara a un usuari corrent val a dir que és atractiu pel disseny i pel software que porta. En aquest últim punt recalcar una excelsa integració de totes les aplicacions que venen amb el sistema. En particular cobreixen la gran majoria de necessitats (o si més no a nivell bà sic) d'un usuari convencional: correu electrònic, música, processament senzill de text, gravació de CD-R, navegació per internet, etc.
Com a entorn per a un desenvolupador el seu atractiu es troba en la seva natura UNIX i en eines proporcionades per la pròpia Apple de forma gratuïta, en particular de l'eina XCode que és un complet entorn de programació. Apple sap que els desenvolupadors són normalment la punta de llança i els ofereix una solució amigable d'un entorn potent com XCode. Aquest paquet incorpora molta documentació, diversos kits de desenvolupament i, com no, la famÃlia de compiladors de GNU, GCC. Inconvenients sempre n'hi ha arreu. El preu és força car. PC's portà tils de preu similar tenen molts cops més molta més potència. Però clar, Apple fa pagar l'exclusivitat del seu sistema. Un portatil de disseny acurat, un software molt vistós, cuidat fins a l'últim detall i molt agradable a la vista. I un sistema operatiu bastit en la robustesa de UNIX. Però no només això, compatibilitat total amb el hardware que ve equipat. Tot això no hi és en un portà til de PC, Apple ho sap i ho cobra. 07:55
Quan reproduïm un CD de música posat al lector, o gravadora, de CD/DVD del nostre ordinador, la gran majoria de cops li demanem que es comporti com un lector de CD de música convencional. El so s'envia directament a la tarja de so que es limita a fer-lo sortir directament pels altaveus.
Aquesta és l'aproximació que prenen la gran majoria d'aplicacions de reproduccio de CD. Té avantatges: no afegeix cap cost de processament per a la CPU ja que el lector s'encarrega de la feina. Llegeix el CD com si fos un lector de música de cadena, converteix la música a analògic i l'envia a la tarja de so per un cable que hem instal·lat a tal efecte. La tarja de so s'encarrega d'enviar-ho a la sortida sense fer-ne cap processament. També te l'avantatge que no ocupa un dispositiu d'à udio i per tant no porta els problemes perquè una aplicació s'ha apropiat del dispositiu de so. És aquesta manca de processament que pot portar-nos algun problema. En general no és possible capturar el so que surt pels altaveus. Capturar el so del CD pot ser útil per exemple quan hem muntat una rà dio i en comptes d'usar una llista de reproducció capturem el so per a retransmetre'l. També ens pot passar que no tinguem el cable connectat del CD a la tarja de so (per exemple, tenim dos lectors de CD) i per algun motiu volem que sonin el dos alhora. L'extracció digital consisteix en llegir les dades del CD directament i enviar-les a la tarja de so perquè les processi. Això fa que ara el so surti per la tarja de so. Té l'avantatge que podem capturar aquest so (si la tarja és full duplex que quasi totes ho són). Ara el control del volum ja no serà el del CD sinó el de PCM (o Wave). Inconvenient és que hi ha un major cost de processament: cal enviar-ho a la tarja de so i ocuparem el dispositiu d'à udio. També te l'avantatge que el lector no cal que estigui connectat a la tarja de so. El reproductor de so XMMS porta un connector (plugin) d'entrada per al CD (libcdaudio.so). En una de les opcions es pot configurar si es vol usar la sortida analògica o l'extracció digital. Si disposeu dels drivers i les eines d'ALSA i de l'eina cdparanoia es pot aconseguir un efecte similar. Primer creem una pipe amb nom on el programa aplay (ALSA player) pugui llegir. Li indicarem que és so de CD directe (16 bit little endian, 44100, stereo) amb -f cd. $ mkfifo soCD $ aplay -f cd soCDAra en un altre terminal li direm a cdparanoia que extragui el so de les pistes però sense aplicar correcció d'errors (-Z). La correcció d'errors reduiria molt la velocitat d'extracció. Li indicarem que extragui el so en format little endian perquè l'aplay el pugui fer sonar (-R). També hem indicat que extragui a partir de la primera pista. Finalment li diem que ho faci a la pipe amb nom que hem creat i que aplay està llegint. $ cdparanoia -Z -R 1 soCD07:55
El meu ordinador d'escriptori té una placa mare Asus A7S333 amb chipset SiS 745. Com ja vaig comentar en el m'agrada apagar el PC i que s'apagui sol.
Malauradament aquest chipset té algun comportament mÃstic inexplicable i l'ordinador no sap apagar-se sol. Un cop premut el botó i iniciat el procés d'apagat, al final no es desconnecta del corrent i es limita a mostrar Power down. Després de molta investigació empÃrica he descobert quines son les opcions que fa que es desconnecti correctament del corrent. Han estat moltes hores de recompilar el kernel, reiniciar, provar d'apagar i tornar a recompilar... El problema principal són els canvis al codi de ACPI del kernel. Cada versió de 2.6.x porta codi molt diferent que fa que calgui canviar les opcions. Al final la combinació que sembla que funciona bé per a kernels 2.6.6 i superior és la següent:
Aquest post està dedicat a tots els propietaris de la placa Asus A7S333 que desitgen fervorosament que sà piga apagar-se sola a Linux. Espero que serveixi a algú més que a mi :) |
apadrinamentsAjuda a fer crèixer la barra verda amb les teves donacions!
8% (20,0 de 256,0€) 61% (190,0 de 314,0€) 88% (1.011,0 de 1.144,5€) 0% (0,0 de 374,1€) 4% (50,0 de 1.235,0€) 47% (545,0 de 1.170,0€) 61% (700,0 de 1.155,0€) comesfa.orgel teu usuariopcionsQui està en lÃniaAra hi han 3 usuaris i 354 convidats connectats.
Usuaris connectats:
és populard'avui... |